testStructsContainingMaybe_test.go 5.17 KB
Newer Older
1
package gengo
2 3 4 5

import (
	"testing"

6
	"github.com/ipld/go-ipld-prime"
7 8 9
	"github.com/ipld/go-ipld-prime/schema"
)

10 11 12 13
// TestStructsContainingMaybe checks all the variations of "nullable" and "optional" on struct fields.
// It does this twice: once for the child maybes being implemented with pointers,
// and once with maybes implemented as embeds.
// The child values are scalars.
14
//
15 16 17
// Both type-level generic build and access as well as representation build and access are exercised;
// the representation used is map (the native representation for structs).
func TestStructsContainingMaybe(t *testing.T) {
18 19
	t.Parallel()

20 21
	// Type declarations.
	//  The tests here will all be targetted against this "Stroct" type.
22 23 24 25 26 27 28 29 30
	ts := schema.TypeSystem{}
	ts.Init()
	adjCfg := &AdjunctCfg{
		maybeUsesPtr: map[schema.TypeName]bool{},
	}
	ts.Accumulate(schema.SpawnString("String"))
	ts.Accumulate(schema.SpawnStruct("Stroct",
		[]schema.StructField{
			// Every field in this struct (including their order) is exercising an interesting case...
31 32 33 34 35
			schema.SpawnStructField("f1", "String", false, false), // plain field.
			schema.SpawnStructField("f2", "String", true, false),  // optional; later we have more than one optional field, nonsequentially.
			schema.SpawnStructField("f3", "String", false, true),  // nullable; but required.
			schema.SpawnStructField("f4", "String", true, true),   // optional and nullable; trailing optional.
			schema.SpawnStructField("f5", "String", true, false),  // optional; and the second one in a row, trailing.
36 37 38 39 40 41 42 43
		},
		schema.SpawnStructRepresentationMap(map[string]string{
			"f1": "r1",
			"f2": "r2",
			"f3": "r3",
			"f4": "r4",
		}),
	))
44

Eric Myhre's avatar
Eric Myhre committed
45
	// There's a lot of cases to cover so a shorthand code labels each case for clarity:
46 47 48
	//  - 'v' -- value in that entry
	//  - 'n' -- null in that entry
	//  - 'z' -- absent entry
Eric Myhre's avatar
Eric Myhre committed
49
	// There's also a semantic description of the main detail being probed suffixed to the shortcode.
50 51
	specs := []testcase{
		{
Eric Myhre's avatar
Eric Myhre committed
52
			name:     "vvvvv-AllFieldsSet",
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
			typeJson: `{"f1":"a","f2":"b","f3":"c","f4":"d","f5":"e"}`,
			reprJson: `{"r1":"a","r2":"b","r3":"c","r4":"d","f5":"e"}`,
			typePoints: []testcasePoint{
				{"", ipld.ReprKind_Map},
				{"f1", "a"},
				{"f2", "b"},
				{"f3", "c"},
				{"f4", "d"},
				{"f5", "e"},
			},
			reprPoints: []testcasePoint{
				{"", ipld.ReprKind_Map},
				{"r1", "a"},
				{"r2", "b"},
				{"r3", "c"},
				{"r4", "d"},
				{"f5", "e"},
			},
		},
		{
Eric Myhre's avatar
Eric Myhre committed
73
			name:     "vvnnv-Nulls",
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
			typeJson: `{"f1":"a","f2":"b","f3":null,"f4":null,"f5":"e"}`,
			reprJson: `{"r1":"a","r2":"b","r3":null,"r4":null,"f5":"e"}`,
			typePoints: []testcasePoint{
				{"", ipld.ReprKind_Map},
				{"f1", "a"},
				{"f2", "b"},
				{"f3", ipld.Null},
				{"f4", ipld.Null},
				{"f5", "e"},
			},
			reprPoints: []testcasePoint{
				{"", ipld.ReprKind_Map},
				{"r1", "a"},
				{"r2", "b"},
				{"r3", ipld.Null},
				{"r4", ipld.Null},
				{"f5", "e"},
			},
		},
		{
Eric Myhre's avatar
Eric Myhre committed
94
			name:     "vzvzv-AbsentOptionals",
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
			typeJson: `{"f1":"a","f3":"c","f5":"e"}`,
			reprJson: `{"r1":"a","r3":"c","f5":"e"}`,
			typePoints: []testcasePoint{
				{"", ipld.ReprKind_Map},
				{"f1", "a"},
				{"f2", ipld.Absent},
				{"f3", "c"},
				{"f4", ipld.Absent},
				{"f5", "e"},
			},
			reprPoints: []testcasePoint{
				{"", ipld.ReprKind_Map},
				{"r1", "a"},
				//{"r2", ipld.ErrNotExists{}}, // TODO: need better error typing from traversal package.
				{"r3", "c"},
				//{"r4", ipld.ErrNotExists{}}, // TODO: need better error typing from traversal package.
				{"f5", "e"},
			},
			typeItr: []entry{
				{"f1", "a"},
				{"f2", ipld.Absent},
				{"f3", "c"},
				{"f4", ipld.Absent},
				{"f5", "e"},
			},
		},
		{
Eric Myhre's avatar
Eric Myhre committed
122
			name:     "vvnzz-AbsentTrailingOptionals",
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
			typeJson: `{"f1":"a","f2":"b","f3":null}`,
			reprJson: `{"r1":"a","r2":"b","r3":null}`,
			typePoints: []testcasePoint{
				{"", ipld.ReprKind_Map},
				{"f1", "a"},
				{"f2", "b"},
				{"f3", ipld.Null},
				{"f4", ipld.Absent},
				{"f5", ipld.Absent},
			},
			reprPoints: []testcasePoint{
				{"", ipld.ReprKind_Map},
				{"r1", "a"},
				{"r2", "b"},
				{"r3", ipld.Null},
				//{"r4", ipld.ErrNotExists{}}, // TODO: need better error typing from traversal package.
				//{"f5", ipld.ErrNotExists{}}, // TODO: need better error typing from traversal package.
			},
			typeItr: []entry{
				{"f1", "a"},
				{"f2", "b"},
				{"f3", ipld.Null},
145 146
				{"f4", ipld.Absent},
				{"f5", ipld.Absent},
147 148 149 150
			},
		},
	}

151 152 153
	// And finally, launch tests! ...while specializing the adjunct config a bit.
	t.Run("maybe-using-embed", func(t *testing.T) {
		adjCfg.maybeUsesPtr["String"] = false
154

155 156
		prefix := "stroct"
		pkgName := "main"
157
		genAndCompileAndTest(t, prefix, pkgName, ts, adjCfg, func(t *testing.T, getPrototypeByName func(string) ipld.NodePrototype) {
158 159 160
			for _, tcase := range specs {
				tcase.Test(t, getPrototypeByName("Stroct"), getPrototypeByName("Stroct.Repr"))
			}
161 162 163
		})
	})
	t.Run("maybe-using-ptr", func(t *testing.T) {
164
		adjCfg.maybeUsesPtr["String"] = true
165 166 167

		prefix := "stroct2"
		pkgName := "main"
168
		genAndCompileAndTest(t, prefix, pkgName, ts, adjCfg, func(t *testing.T, getPrototypeByName func(string) ipld.NodePrototype) {
169 170 171
			for _, tcase := range specs {
				tcase.Test(t, getPrototypeByName("Stroct"), getPrototypeByName("Stroct.Repr"))
			}
172 173 174
		})
	})
}