github.com/ipld/go-ipld-prime@v0.21.0/schema/dsl/parse_test.go (about) 1 package schemadsl_test 2 3 import ( 4 "bytes" 5 "flag" 6 "os" 7 "path/filepath" 8 "regexp" 9 "strings" 10 "testing" 11 12 ipldjson "github.com/ipld/go-ipld-prime/codec/json" 13 "github.com/ipld/go-ipld-prime/node/bindnode" 14 "github.com/ipld/go-ipld-prime/schema" 15 schemadmt "github.com/ipld/go-ipld-prime/schema/dmt" 16 schemadsl "github.com/ipld/go-ipld-prime/schema/dsl" 17 "gopkg.in/yaml.v2" 18 19 qt "github.com/frankban/quicktest" 20 ) 21 22 var update = flag.Bool("update", false, "update testdata files in-place") 23 24 func TestParseSchemaSchema(t *testing.T) { 25 t.Parallel() 26 27 inputSchema := "../../.ipld/specs/schemas/schema-schema.ipldsch" 28 inputJSON := "../../.ipld/specs/schemas/schema-schema.ipldsch.json" 29 30 src, err := os.ReadFile(inputSchema) 31 qt.Assert(t, err, qt.IsNil) 32 33 srcJSON, err := os.ReadFile(inputJSON) 34 qt.Assert(t, err, qt.IsNil) 35 36 testParse(t, string(src), string(srcJSON), func(updated string) { 37 err := os.WriteFile(inputJSON, []byte(updated), 0o777) 38 qt.Assert(t, err, qt.IsNil) 39 }) 40 } 41 42 type yamlFixture struct { 43 Schema string 44 Canonical string `yaml:",omitempty"` 45 Expected string 46 ExpectedParsed interface{} `yaml:",omitempty"` 47 Blocks []yamlFixtureBlock `yaml:",omitempty"` 48 BadBlocks []string `yaml:"badBlocks,omitempty"` 49 BadBlocksParsed []interface{} `yaml:",omitempty"` 50 } 51 52 type yamlFixtureBlock struct { 53 Actual string `yaml:",omitempty"` 54 ActualParsed interface{} `yaml:",omitempty"` 55 Expected string `yaml:",omitempty"` 56 ExpectedParsed interface{} `yaml:",omitempty"` 57 } 58 59 func TestParse(t *testing.T) { 60 t.Parallel() 61 62 matches, err := filepath.Glob("../../.ipld/specs/schemas/tests/*.yml") 63 qt.Assert(t, err, qt.IsNil) 64 qt.Assert(t, matches, qt.Not(qt.HasLen), 0) 65 66 for _, ymlPath := range matches { 67 ymlPath := ymlPath // do not reuse range var 68 name := filepath.Base(ymlPath) 69 70 t.Run(name, func(t *testing.T) { 71 t.Parallel() 72 73 data, err := os.ReadFile(ymlPath) 74 qt.Assert(t, err, qt.IsNil) 75 76 var fixt yamlFixture 77 err = yaml.Unmarshal(data, &fixt) 78 qt.Assert(t, err, qt.IsNil) 79 80 testParse(t, fixt.Schema, fixt.Expected, func(updated string) { 81 updated = strings.Replace(updated, "\t", " ", -1) 82 fixt.Expected = updated 83 84 data, err = yaml.Marshal(&fixt) 85 qt.Assert(t, err, qt.IsNil) 86 87 // Note that this will strip comments. 88 // Probably don't commit its changes straight away. 89 err = os.WriteFile(ymlPath, data, 0777) 90 qt.Assert(t, err, qt.IsNil) 91 }) 92 }) 93 } 94 } 95 96 func testParse(t *testing.T, inSchema, inJSON string, updateFn func(string)) { 97 t.Helper() 98 99 inJSON = strings.Replace(inJSON, " ", "\t", -1) // fix non-tab indenting 100 crre := regexp.MustCompile(`\r?\n`) 101 inJSON = crre.ReplaceAllString(inJSON, "\n") // fix windows carriage-return 102 103 sch, err := schemadsl.ParseBytes([]byte(inSchema)) 104 qt.Assert(t, err, qt.IsNil) 105 106 // Ensure the parsed schema compiles as expected. 107 { 108 var ts schema.TypeSystem 109 ts.Init() 110 err := schemadmt.Compile(&ts, sch) 111 qt.Assert(t, err, qt.IsNil) 112 113 qt.Assert(t, ts.Names(), qt.Not(qt.HasLen), 0) 114 } 115 116 // Ensure we can encode the schema as the json codec, 117 // and that it results in the same bytes as the ipldsch.json file. 118 { 119 node := bindnode.Wrap(sch, schemadmt.Prototypes.Schema.Type()) 120 121 var buf bytes.Buffer 122 err := ipldjson.Encode(node.Representation(), &buf) 123 qt.Assert(t, err, qt.IsNil) 124 125 // If we're updating, write to the file. 126 // Otherwise, expect the files to be equal. 127 got := buf.String() 128 if *update { 129 updateFn(got) 130 return 131 } 132 qt.Assert(t, got, qt.Equals, inJSON, 133 qt.Commentf("run 'go test -update' to write to the iplsch.json file")) 134 } 135 136 // TODO: ensure that doing a json codec decode results in the same Schema Go 137 // value that we got by parsing the DSL. 138 }