schemaScalars.go 3.22 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
package tests

import (
	"fmt"
	"testing"

	qt "github.com/frankban/quicktest"

	"github.com/ipld/go-ipld-prime"
	"github.com/ipld/go-ipld-prime/schema"
)

func assignValue(am ipld.NodeAssembler, value interface{}) error {
	switch value := value.(type) {
	case bool:
		return am.AssignBool(value)
	case int64:
		return am.AssignInt(value)
	case float64:
		return am.AssignFloat(value)
	case string:
		return am.AssignString(value)
	case []byte:
		return am.AssignBytes(value)
	default:
		panic(fmt.Sprintf("%T", value))
	}
}

func SchemaTestScalars(t *testing.T, engine Engine) {
	ts := schema.TypeSystem{}
	ts.Init()

	ts.Accumulate(schema.SpawnBool("Bool"))
	ts.Accumulate(schema.SpawnInt("Int"))
	ts.Accumulate(schema.SpawnFloat("Float"))
	ts.Accumulate(schema.SpawnString("String"))
	ts.Accumulate(schema.SpawnBytes("Bytes"))
	engine.Init(t, ts)

	var tests = []struct {
		name  string
		kind  ipld.Kind
		value interface{}
	}{
		{"Bool", ipld.Kind_Bool, true},
		{"Int", ipld.Kind_Int, int64(23)},
		{"Float", ipld.Kind_Float, 12.25},
		{"String", ipld.Kind_String, "foo"},
		{"Bytes", ipld.Kind_Bytes, []byte("bar")},
	}

	// We test each of the five scalar prototypes in subtests.
	for _, testProto := range tests {
		np := engine.PrototypeByName(testProto.name)

		// For each prototype, we try assigning all scalar values.
		for _, testAssign := range tests {

			// We try both AssignKind and AssignNode.
			for _, useAssignNode := range []bool{false, true} {
				testName := fmt.Sprintf("%s-Assign%s", testProto.name, testAssign.name)
				if useAssignNode {
					testName = fmt.Sprintf("%s-AssignNode-%s", testProto.name, testAssign.name)
				}
				t.Run(testName, func(t *testing.T) {
					nb := np.NewBuilder()

					// Assigning the right value for the kind should succeed.
					var err error
					if useAssignNode {
						np2 := engine.PrototypeByName(testAssign.name)
						nb2 := np2.NewBuilder()
						qt.Assert(t, assignValue(nb2, testAssign.value), qt.IsNil)
						n2 := nb2.Build()

						err = nb.AssignNode(n2)
					} else {
						err = assignValue(nb, testAssign.value)
					}
					if testAssign.kind == testProto.kind {
						qt.Assert(t, err, qt.IsNil)
					} else {
						qt.Assert(t, err, qt.Not(qt.IsNil))

						// Assign something anyway, just so we can Build later.
						err := assignValue(nb, testProto.value)
						qt.Assert(t, err, qt.IsNil)
					}

					n := nb.Build()

					// For both the regular node and its repr version,
					// getting the right value for the kind should work.
					for _, n := range []ipld.Node{
						n,
						n.(schema.TypedNode).Representation(),
					} {
						var gotValue interface{}
						err = nil
						switch testAssign.kind {
						case ipld.Kind_Bool:
							gotValue, err = n.AsBool()
						case ipld.Kind_Int:
							gotValue, err = n.AsInt()
						case ipld.Kind_Float:
							gotValue, err = n.AsFloat()
						case ipld.Kind_String:
							gotValue, err = n.AsString()
						case ipld.Kind_Bytes:
							gotValue, err = n.AsBytes()
						default:
							t.Fatal(testAssign.kind)
						}
						if testAssign.kind == testProto.kind {
							qt.Assert(t, err, qt.IsNil)
							qt.Assert(t, gotValue, qt.DeepEquals, testAssign.value)
						} else {
							qt.Assert(t, err, qt.Not(qt.IsNil))
						}
					}
				})
			}
		}
	}
}