Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 8 additions & 24 deletions e2e/e2e_core_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,11 @@ func TestCore_Run(t *testing.T) {
t.Fatal(err)
}

address, err := chooseOpenAddress(t)
if err != nil {
t.Fatal(err)
}
cmd := newCmd(t, "run", "--address", address)
if err := cmd.Start(); err != nil {
t.Fatal(err)
}
cmd := newCmd(t, "run", "--json")
address, cleanup := parseRunJSON(t, cmd)
defer cleanup()

// Wait for echo
if !waitFor(t, "http://"+address) {
if !waitFor(t, address) {
t.Fatal("service does not appear to have started correctly.")
}

Expand Down Expand Up @@ -279,15 +273,10 @@ func TestCore_Invoke(t *testing.T) {
// ----------------------------------------
// Runs the function locally, which `func invoke` will invoke when
// it detects it is running.
address, err := chooseOpenAddress(t)
if err != nil {
t.Fatal(err)
}
cmd := newCmd(t, "run", "--json")
address, cleanup := parseRunJSON(t, cmd)
defer cleanup()

cmd := newCmd(t, "run", "--address", address)
if err := cmd.Start(); err != nil {
t.Fatal(err)
}
run := cmd // for the closure
defer func() {
// ^C the running function
Expand All @@ -296,12 +285,7 @@ func TestCore_Invoke(t *testing.T) {
}
}()

// TODO: complete implementation of `func run --json` structured output
// such that we can parse it for the actual listen address in the case
// that there is already something else running on 8080
// https://github.com/knative/func/issues/3198
// https://github.com/knative/func/issues/3199
if !waitFor(t, "http://"+address) {
if !waitFor(t, address) {
t.Fatal("service does not appear to have started correctly.")
}

Expand Down
21 changes: 8 additions & 13 deletions e2e/e2e_matrix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,11 @@ func TestMatrix_Run(t *testing.T) {
cleanImages(t, name)
})

// Choose an address ahead of time
address, err := chooseOpenAddress(t)
if err != nil {
t.Fatal(err)
}

// func init
init := []string{"init", "-l", runtime, "-t", template}

// func run
run := []string{"run", "--builder", builder, "--address", address}
run := []string{"run", "--builder", builder, "--json"}

// Language and architecture special treatment
// - Skips tests if the builder is not supported
Expand All @@ -66,15 +60,12 @@ func TestMatrix_Run(t *testing.T) {
}

// Run
// ---
cmd := newCmd(t, run...)
if err := cmd.Start(); err != nil {
t.Fatal(err)
}
address, cleanup := parseRunJSON(t, cmd)
defer cleanup()

// Ensure the Function comes up

if !waitFor(t, "http://"+address,
if !waitFor(t, address,
withWaitTimeout(timeout),
withTemplate(template)) {
t.Fatal("service does not appear to have started correctly.")
Expand Down Expand Up @@ -235,6 +226,10 @@ func matrixExceptionsShared(t *testing.T, initArgs []string, funcRuntime, builde
if funcRuntime == "python" && builder == "pack" {
t.Skip("The pack builder does not currently support Python Functions")
}
// Skip Host builder (not supported)
if funcRuntime == "python" && builder == "host" {
t.Skip("The host builder does not currently support Python Functions")
}

// Echo Implementation
// Replace the simple "OK" implementation with an echo.
Expand Down
48 changes: 48 additions & 0 deletions e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ See README.md for more details.
package e2e

import (
"bytes"
"context"
"encoding/json"
"fmt"
Expand Down Expand Up @@ -1154,3 +1155,50 @@ func chooseOpenAddress(t *testing.T) (address string, err error) {
defer l.Close()
return l.Addr().String(), nil
}

// parseRunJSON parses JSON output from "func run --json" and returns the
// function's address and a cleanup function that must be deferred.
func parseRunJSON(t *testing.T, cmd *exec.Cmd) (string, func()) {
t.Helper()

stdoutReader, stdoutWriter := io.Pipe()
stderr := &bytes.Buffer{}
cmd.Stdout = stdoutWriter
cmd.Stderr = stderr

if err := cmd.Start(); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we might use blocking cmd.Run() but it must be used after the gorutine is spawn.

t.Fatal(err)
}

type runOutput struct {
Address string `json:"address"`
Host string `json:"host"`
Port string `json:"port"`
}

addressChan := make(chan string, 1)
errChan := make(chan error, 1)

go func() {
var result runOutput
decoder := json.NewDecoder(stdoutReader)
if err := decoder.Decode(&result); err != nil {
errChan <- fmt.Errorf("failed to decode JSON output: %w", err)
return
}
addressChan <- result.Address
io.Copy(io.Discard, stdoutReader) // Prevent blocking
}()

var address string
select {
case address = <-addressChan:
t.Logf("Function running on %s (from JSON output)", address)
case err := <-errChan:
t.Fatalf("JSON parsing error: %v\nstderr: %s", err, stderr.String())
case <-time.After(5 * time.Minute):
t.Fatalf("timeout waiting for func run JSON output. stderr: %s", stderr.String())
}

return address, func() { stdoutWriter.Close() }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cannot we close this writer within the function?

}
Loading