Break up TestExecute into subtests

This commit is contained in:
Tim Van Baak 2025-02-09 22:33:42 -08:00
parent 834eb8ae62
commit 659b00bc22

View File

@ -6,19 +6,19 @@ import (
) )
func TestExecute(t *testing.T) { func TestExecute(t *testing.T) {
assertLen := func(items []Item, length int) { assertLen := func(t *testing.T, items []Item, length int) {
t.Helper() t.Helper()
if len(items) != length { if len(items) != length {
t.Fatalf("Expected %d items, got %d", length, len(items)) t.Fatalf("Expected %d items, got %d", length, len(items))
} }
} }
assertNil := func(err error) { assertNil := func(t *testing.T, err error) {
t.Helper() t.Helper()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
assertNotNil := func(err error) { assertNotNil := func(t *testing.T, err error) {
t.Helper() t.Helper()
if err == nil { if err == nil {
t.Fatal("expected err") t.Fatal("expected err")
@ -29,138 +29,165 @@ func TestExecute(t *testing.T) {
return item, err return item, err
} }
res, err := execute([]string{"true"}) t.Run("Noop", func(t *testing.T) {
assertNil(err) res, err := execute([]string{"true"})
assertLen(res, 0) assertNil(t, err)
assertLen(t, res, 0)
// Exit with error code })
res, err = execute([]string{"false"})
assertNotNil(err) t.Run("ExitWithErrorCode", func(t *testing.T) {
assertLen(res, 0) res, err := execute([]string{"false"})
assertNotNil(t, err)
res, err = execute([]string{"sh", "-c", "exit 22"}) assertLen(t, res, 0)
assertNotNil(err) })
assertLen(res, 0)
t.Run("ExitWithSpecificErrorCode", func(t *testing.T) {
// Timeout res, err := execute([]string{"sh", "-c", "exit 22"})
res, _, err = Execute("_", []string{"sleep", "10"}, nil, nil, "", time.Millisecond, nil) assertNotNil(t, err)
assertNotNil(err) assertLen(t, res, 0)
assertLen(res, 0) })
// Returning items t.Run("Timeout", func(t *testing.T) {
res, err = execute([]string{"jq", "-cn", `{id: "foo"}`}) res, _, err := Execute("_", []string{"sleep", "10"}, nil, nil, "", time.Millisecond, nil)
assertNil(err) assertNotNil(t, err)
assertLen(res, 1) assertLen(t, res, 0)
if res[0].Id != "foo" { })
t.Fatal("jq -cn test failed")
} t.Run("ReturningItems", func(t *testing.T) {
res, err := execute([]string{"jq", "-cn", `{id: "foo"}`})
// Read from stdin assertNil(t, err)
res, _, err = Execute("_", []string{"jq", "-cR", `{id: .}`}, nil, nil, "bar", time.Minute, nil) assertLen(t, res, 1)
assertNil(err) if res[0].Id != "foo" {
assertLen(res, 1) t.Fatal("jq -cn test failed")
if res[0].Id != "bar" { }
t.Fatal("jq -cR test failed") })
}
t.Run("ReadFromStdin", func(t *testing.T) {
// Set env res, _, err := Execute("_", []string{"jq", "-cR", `{id: .}`}, nil, nil, "bar", time.Minute, nil)
res, _, err = Execute("_", []string{"jq", "-cn", `{id: env.HELLO}`}, []string{"HELLO=baz"}, nil, "", time.Minute, nil) assertNil(t, err)
assertNil(err) assertLen(t, res, 1)
assertLen(res, 1) if res[0].Id != "bar" {
if res[0].Id != "baz" { t.Fatal("jq -cR test failed")
t.Fatal("jq -cn env test failed") }
} })
// With logging on stderr t.Run("SetEnv", func(t *testing.T) {
res, err = execute([]string{"sh", "-c", `echo 1>&2 Hello; jq -cn '{id: "box"}'; echo 1>&2 World`}) res, _, err := Execute("_", []string{"jq", "-cn", `{id: env.HELLO}`}, []string{"HELLO=baz"}, nil, "", time.Minute, nil)
assertNil(err) assertNil(t, err)
assertLen(res, 1) assertLen(t, res, 1)
if res[0].Id != "box" { if res[0].Id != "baz" {
t.Fatal("stderr test failed") t.Fatal("jq -cn env test failed")
} }
})
// Unsupported item field is silently discarded t.Run("StderrLogging", func(t *testing.T) {
res, err = execute([]string{"jq", "-cn", `{id: "test", unknownField: "what is this"}`}) res, err := execute([]string{"sh", "-c", `echo 1>&2 Hello; jq -cn '{id: "box"}'; echo 1>&2 World`})
assertNil(err) assertNil(t, err)
assertLen(res, 1) assertLen(t, res, 1)
if res[0].Id != "box" {
// Field with incorrect type fails t.Fatal("stderr test failed")
res, err = execute([]string{"jq", "-cn", `{id: ["list"]}`}) }
assertNotNil(err) })
assertLen(res, 0)
t.Run("UnknownFieldIgnored", func(t *testing.T) {
res, err = execute([]string{"jq", "-cn", `{id: "test", time: "0"}`}) res, err := execute([]string{"jq", "-cn", `{id: "test", unknownField: "what is this"}`})
assertNotNil(err) assertNil(t, err)
assertLen(res, 0) assertLen(t, res, 1)
})
res, err = execute([]string{"jq", "-cn", `{id: null}`})
assertNotNil(err) t.Run("IncorrectIdType", func(t *testing.T) {
assertLen(res, 0) res, err := execute([]string{"jq", "-cn", `{id: ["list"]}`})
assertNotNil(t, err)
// Items with duplicate ids is not a fetch error, but it will fail to update assertLen(t, res, 0)
res, err = execute([]string{"jq", "-cn", `["a", "a"] | .[] | {id: .}`}) })
assertNil(err)
assertLen(res, 2) t.Run("IncorrectTimeType", func(t *testing.T) {
res, err := execute([]string{"jq", "-cn", `{id: "test", time: "0"}`})
// Action keys are detected even with empty values assertNotNil(t, err)
res, err = execute([]string{"jq", "-cn", `{id: "test", action: {"hello": null}}`}) assertLen(t, res, 0)
assertNil(err) })
assertLen(res, 1)
if res[0].Action["hello"] == nil { t.Run("NullId", func(t *testing.T) {
t.Fatal("missing hello action") res, err := execute([]string{"jq", "-cn", `{id: null}`})
} assertNotNil(t, err)
if res[0].Action["goodbye"] != nil { assertLen(t, res, 0)
t.Fatal("nonexistent action should key to nil in Action") })
}
// TODO maybe this *should* be an Execute error, via a map[string]bool
res, err = execute([]string{"jq", "-cn", `{id: "test", action: {"hello": ""}}`}) t.Run("DuplicateItemIds", func(t *testing.T) {
assertNil(err) res, err := execute([]string{"jq", "-cn", `["a", "a"] | .[] | {id: .}`})
assertLen(res, 1) assertNil(t, err)
if res[0].Action["hello"] == nil { assertLen(t, res, 2)
t.Fatal("missing hello action") })
}
t.Run("ActionNullValueOk", func(t *testing.T) {
res, err = execute([]string{"jq", "-cn", `{id: "test", action: {"hello": []}}`}) res, err := execute([]string{"jq", "-cn", `{id: "test", action: {"hello": null}}`})
assertNil(err) assertNil(t, err)
assertLen(res, 1) assertLen(t, res, 1)
if res[0].Action["hello"] == nil { if res[0].Action["hello"] == nil {
t.Fatal("missing hello action") t.Fatal("missing hello action")
} }
if res[0].Action["goodbye"] != nil {
res, err = execute([]string{"jq", "-cn", `{id: "test", action: {"hello": {}}}`}) t.Fatal("nonexistent action should key to nil in Action")
assertNil(err) }
assertLen(res, 1) })
if res[0].Action["hello"] == nil {
t.Fatal("missing hello action") t.Run("ActionEmptyStringOk", func(t *testing.T) {
} res, err := execute([]string{"jq", "-cn", `{id: "test", action: {"hello": ""}}`})
assertNil(t, err)
// Read state assertLen(t, res, 1)
argv := []string{"sh", "-c", `cat $STATE_PATH | jq -cR '{id: "greeting", title: .} | .title = "Hello " + .title'`} if res[0].Action["hello"] == nil {
res, _, err = Execute("_", argv, nil, []byte("world"), "", time.Minute, nil) t.Fatal("missing hello action")
assertNil(err) }
assertLen(res, 1) })
if res[0].Title != "Hello world" {
t.Fatalf("expected 'Hello world' from read state, got '%s'", res[0].Title) t.Run("ActionEmptyArrayOk", func(t *testing.T) {
} res, err := execute([]string{"jq", "-cn", `{id: "test", action: {"hello": []}}`})
assertNil(t, err)
// Write state assertLen(t, res, 1)
argv = []string{"sh", "-c", `printf "Hello world" > $STATE_PATH; jq -cn '{id: "test"}'`} if res[0].Action["hello"] == nil {
res, newState, err := Execute("_", argv, nil, nil, "", time.Minute, nil) t.Fatal("missing hello action")
assertNil(err) }
assertLen(res, 1) })
if string(newState) != "Hello world" {
t.Fatalf("expected 'Hello world' from write state, got %s", string(newState)) t.Run("ActionEmptyObjectOk", func(t *testing.T) {
} res, err := execute([]string{"jq", "-cn", `{id: "test", action: {"hello": {}}}`})
assertNil(t, err)
// Postprocessing function assertLen(t, res, 1)
argv = []string{"jq", "-cn", `{id: "foo"}`} if res[0].Action["hello"] == nil {
res, _, err = Execute("_", argv, nil, nil, "", time.Minute, func(item Item) Item { t.Fatal("missing hello action")
item.Ttl = 123456 }
return item })
t.Run("ReadState", func(t *testing.T) {
argv := []string{"sh", "-c", `cat $STATE_PATH | jq -cR '{id: "greeting", title: .} | .title = "Hello " + .title'`}
res, _, err := Execute("_", argv, nil, []byte("world"), "", time.Minute, nil)
assertNil(t, err)
assertLen(t, res, 1)
if res[0].Title != "Hello world" {
t.Fatalf("expected 'Hello world' from read state, got '%s'", res[0].Title)
}
})
t.Run("WriteState", func(t *testing.T) {
argv := []string{"sh", "-c", `printf "Hello world" > $STATE_PATH; jq -cn '{id: "test"}'`}
res, newState, err := Execute("_", argv, nil, nil, "", time.Minute, nil)
assertNil(t, err)
assertLen(t, res, 1)
if string(newState) != "Hello world" {
t.Fatalf("expected 'Hello world' from write state, got %s", string(newState))
}
})
t.Run("PostprocessSetTtl", func(t *testing.T) {
argv := []string{"jq", "-cn", `{id: "foo"}`}
res, _, err := Execute("_", argv, nil, nil, "", time.Minute, func(item Item) Item {
item.Ttl = 123456
return item
})
assertNil(t, err)
assertLen(t, res, 1)
if res[0].Ttl != 123456 {
t.Fatalf("expected ttl to be set to 123456, got %d", res[0].Ttl)
}
}) })
assertNil(err)
assertLen(res, 1)
if res[0].Ttl != 123456 {
t.Fatalf("expected ttl to be set to 123456, got %d", res[0].Ttl)
}
} }