From ac672fa08a1f8cb13538e26169cbf4c59dac5bcd Mon Sep 17 00:00:00 2001 From: Rod Vagg Date: Tue, 24 May 2022 14:04:33 +1000 Subject: [PATCH] fix(bindnode): more helpful error message for enum value footgun Fixes: https://github.com/ipld/go-ipld-prime/issues/348 --- node/bindnode/api_test.go | 38 ++++++++++++++++++++++++++++++++++++++ node/bindnode/repr.go | 6 ++++++ 2 files changed, 44 insertions(+) create mode 100644 node/bindnode/api_test.go diff --git a/node/bindnode/api_test.go b/node/bindnode/api_test.go new file mode 100644 index 00000000..ea7cb12a --- /dev/null +++ b/node/bindnode/api_test.go @@ -0,0 +1,38 @@ +package bindnode_test + +import ( + "testing" + + qt "github.com/frankban/quicktest" + "github.com/ipld/go-ipld-prime" + "github.com/ipld/go-ipld-prime/codec/dagcbor" + "github.com/ipld/go-ipld-prime/node/bindnode" +) + +func TestEnumError(t *testing.T) { + type Action string + const ( + ActionPresent = Action("p") + ActionMissing = Action("m") + ) + type S struct{ Action Action } + + schema := ` + type S struct { + Action Action + } representation tuple + type Action enum { + | Present ("p") + | Missing ("m") + } representation string + ` + + typeSystem, err := ipld.LoadSchemaBytes([]byte(schema)) + qt.Assert(t, err, qt.IsNil) + schemaType := typeSystem.TypeByName("S") + + node := bindnode.Wrap(&S{Action: ActionPresent}, schemaType).Representation() + _, err = ipld.Encode(node, dagcbor.Encode) + qt.Assert(t, err, qt.IsNotNil) + qt.Assert(t, err.Error(), qt.Equals, `AsString: "p" is not a valid member of enum Action (bindnode works at the type level; did you mean "Present"?)`) +} diff --git a/node/bindnode/repr.go b/node/bindnode/repr.go index fbd52861..02b2f058 100644 --- a/node/bindnode/repr.go +++ b/node/bindnode/repr.go @@ -488,6 +488,12 @@ func (w *_nodeRepr) AsString() (string, error) { return s, nil } } + for k, v := range stg { + // a programming error? we may have the enum string value rather than the type + if v == s { + return "", fmt.Errorf("AsString: %q is not a valid member of enum %s (bindnode works at the type level; did you mean %q?)", s, w.schemaType.Name(), k) + } + } return "", fmt.Errorf("AsString: %q is not a valid member of enum %s", s, w.schemaType.Name()) default: return (*_node)(w).AsString()