Skip to content

[Tigron]: expect.JSON comparator and updated volume test #4079

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 14, 2025
Merged
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
42 changes: 11 additions & 31 deletions cmd/nerdctl/volume/volume_inspect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package volume

import (
"crypto/rand"
"encoding/json"
"errors"
"fmt"
"os"
Expand All @@ -31,6 +30,7 @@ import (
"github.com/containerd/nerdctl/mod/tigron/expect"
"github.com/containerd/nerdctl/mod/tigron/require"
"github.com/containerd/nerdctl/mod/tigron/test"
"github.com/containerd/nerdctl/mod/tigron/tig"

"github.com/containerd/nerdctl/v2/pkg/inspecttypes/native"
"github.com/containerd/nerdctl/v2/pkg/testutil/nerdtest"
Expand Down Expand Up @@ -99,15 +99,11 @@ func TestVolumeInspect(t *testing.T) {
return &test.Expected{
Output: expect.All(
expect.Contains(data.Get("vol1")),
func(stdout string, info string, t *testing.T) {
var dc []native.Volume
if err := json.Unmarshal([]byte(stdout), &dc); err != nil {
t.Fatal(err)
}
expect.JSON([]native.Volume{}, func(dc []native.Volume, info string, t tig.T) {
assert.Assert(t, len(dc) == 1, fmt.Sprintf("one result, not %d", len(dc))+info)
assert.Assert(t, dc[0].Name == data.Get("vol1"), fmt.Sprintf("expected name to be %q (was %q)", data.Get("vol1"), dc[0].Name)+info)
assert.Assert(t, dc[0].Labels == nil, fmt.Sprintf("expected labels to be nil and were %v", dc[0].Labels)+info)
},
}),
),
}
},
Expand All @@ -121,16 +117,12 @@ func TestVolumeInspect(t *testing.T) {
return &test.Expected{
Output: expect.All(
expect.Contains(data.Get("vol2")),
func(stdout string, info string, t *testing.T) {
var dc []native.Volume
if err := json.Unmarshal([]byte(stdout), &dc); err != nil {
t.Fatal(err)
}
expect.JSON([]native.Volume{}, func(dc []native.Volume, info string, t tig.T) {
labels := *dc[0].Labels
assert.Assert(t, len(labels) == 2, fmt.Sprintf("two results, not %d", len(labels)))
assert.Assert(t, labels["foo"] == "fooval", fmt.Sprintf("label foo should be fooval, not %s", labels["foo"]))
assert.Assert(t, labels["bar"] == "barval", fmt.Sprintf("label bar should be barval, not %s", labels["bar"]))
},
}),
),
}
},
Expand All @@ -145,13 +137,9 @@ func TestVolumeInspect(t *testing.T) {
return &test.Expected{
Output: expect.All(
expect.Contains(data.Get("vol1")),
func(stdout string, info string, t *testing.T) {
var dc []native.Volume
if err := json.Unmarshal([]byte(stdout), &dc); err != nil {
t.Fatal(err)
}
expect.JSON([]native.Volume{}, func(dc []native.Volume, info string, t tig.T) {
assert.Assert(t, dc[0].Size == size, fmt.Sprintf("expected size to be %d (was %d)", size, dc[0].Size))
},
}),
),
}
},
Expand All @@ -166,15 +154,11 @@ func TestVolumeInspect(t *testing.T) {
Output: expect.All(
expect.Contains(data.Get("vol1")),
expect.Contains(data.Get("vol2")),
func(stdout string, info string, t *testing.T) {
var dc []native.Volume
if err := json.Unmarshal([]byte(stdout), &dc); err != nil {
t.Fatal(err)
}
expect.JSON([]native.Volume{}, func(dc []native.Volume, info string, t tig.T) {
assert.Assert(t, len(dc) == 2, fmt.Sprintf("two results, not %d", len(dc)))
assert.Assert(t, dc[0].Name == data.Get("vol1"), fmt.Sprintf("expected name to be %q (was %q)", data.Get("vol1"), dc[0].Name))
assert.Assert(t, dc[1].Name == data.Get("vol2"), fmt.Sprintf("expected name to be %q (was %q)", data.Get("vol2"), dc[1].Name))
},
}),
),
}
},
Expand All @@ -190,14 +174,10 @@ func TestVolumeInspect(t *testing.T) {
Errors: []error{errdefs.ErrNotFound, errdefs.ErrInvalidArgument},
Output: expect.All(
expect.Contains(data.Get("vol1")),
func(stdout string, info string, t *testing.T) {
var dc []native.Volume
if err := json.Unmarshal([]byte(stdout), &dc); err != nil {
t.Fatal(err)
}
expect.JSON([]native.Volume{}, func(dc []native.Volume, info string, t tig.T) {
assert.Assert(t, len(dc) == 1, fmt.Sprintf("one result, not %d", len(dc)))
assert.Assert(t, dc[0].Name == data.Get("vol1"), fmt.Sprintf("expected name to be %q (was %q)", data.Get("vol1"), dc[0].Name))
},
}),
),
}
},
Expand Down
17 changes: 17 additions & 0 deletions mod/tigron/expect/comparators.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@
package expect

import (
"encoding/json"
"regexp"
"testing"

"github.com/containerd/nerdctl/mod/tigron/internal/assertive"
"github.com/containerd/nerdctl/mod/tigron/test"
"github.com/containerd/nerdctl/mod/tigron/tig"
)

// All can be used as a parameter for expected.Output to group a set of comparators.
Expand Down Expand Up @@ -69,3 +71,18 @@ func Match(reg *regexp.Regexp) test.Comparator {
assertive.Match(assertive.WithFailLater(t), stdout, reg, info)
}
}

// JSON allows to verify that the output can be marshalled into T, and optionally can be further verified by a provided
// method.
func JSON[T any](obj T, verifier func(T, string, tig.T)) test.Comparator {
return func(stdout, info string, t *testing.T) {
t.Helper()

err := json.Unmarshal([]byte(stdout), &obj)
assertive.ErrorIsNil(assertive.WithFailLater(t), err, "failed to unmarshal JSON from stdout")

if verifier != nil && err == nil {
verifier(obj, info, t)
}
}
}
31 changes: 26 additions & 5 deletions mod/tigron/expect/comparators_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,45 @@ package expect_test
// TODO: add a lot more tests including failure conditions with mimicry

import (
"encoding/json"
"regexp"
"testing"

"github.com/containerd/nerdctl/mod/tigron/expect"
"github.com/containerd/nerdctl/mod/tigron/internal/assertive"
"github.com/containerd/nerdctl/mod/tigron/tig"
)

func TestExpect(t *testing.T) {
t.Parallel()

expect.Contains("b")("a b c", "info", t)
expect.DoesNotContain("d")("a b c", "info", t)
expect.Equals("a b c")("a b c", "info", t)
expect.Match(regexp.MustCompile("[a-z ]+"))("a b c", "info", t)
expect.Contains("b")("a b c", "contains works", t)
expect.DoesNotContain("d")("a b c", "does not contain works", t)
expect.Equals("a b c")("a b c", "equals work", t)
expect.Match(regexp.MustCompile("[a-z ]+"))("a b c", "match works", t)

expect.All(
expect.Contains("b"),
expect.DoesNotContain("d"),
expect.Equals("a b c"),
expect.Match(regexp.MustCompile("[a-z ]+")),
)("a b c", "info", t)
)("a b c", "all", t)

type foo struct {
Foo map[string]string `json:"foo"`
}

data, err := json.Marshal(&foo{
Foo: map[string]string{
"foo": "bar",
},
})

assertive.ErrorIsNil(t, err)

expect.JSON(&foo{}, nil)(string(data), "json, no verifier", t)

expect.JSON(&foo{}, func(obj *foo, info string, t tig.T) {
assertive.IsEqual(t, obj.Foo["foo"], "bar", info)
})(string(data), "json, with verifier", t)
}
Loading