github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/store/nomdl/parser_test.go (about)

     1  // Copyright 2019 Dolthub, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  // This file incorporates work covered by the following copyright and
    16  // permission notice:
    17  //
    18  // Copyright 2017 Attic Labs, Inc. All rights reserved.
    19  // Licensed under the Apache License, version 2.0:
    20  // http://www.apache.org/licenses/LICENSE-2.0
    21  
    22  package nomdl
    23  
    24  import (
    25  	"bytes"
    26  	"context"
    27  	"strings"
    28  	"testing"
    29  
    30  	"github.com/stretchr/testify/assert"
    31  	"github.com/stretchr/testify/require"
    32  
    33  	"github.com/dolthub/dolt/go/store/chunks"
    34  	"github.com/dolthub/dolt/go/store/d"
    35  	"github.com/dolthub/dolt/go/store/types"
    36  )
    37  
    38  func mustString(str string, err error) string {
    39  	d.PanicIfError(err)
    40  	return str
    41  }
    42  
    43  func mustType(typ *types.Type, err error) *types.Type {
    44  	d.PanicIfError(err)
    45  	return typ
    46  }
    47  
    48  func mustValue(val types.Value, err error) types.Value {
    49  	d.PanicIfError(err)
    50  	return val
    51  }
    52  
    53  func newTestValueStore() *types.ValueStore {
    54  	st := &chunks.TestStorage{}
    55  	return types.NewValueStore(st.NewView())
    56  }
    57  
    58  func assertParseType(t *testing.T, code string, expected *types.Type) {
    59  	t.Run(code, func(t *testing.T) {
    60  		actual, err := ParseType(code)
    61  		require.NoError(t, err)
    62  		assert.True(t, expected.Equals(actual), "Expected: %s, Actual: %s", mustString(expected.Describe(context.Background())), mustString(actual.Describe(context.Background())))
    63  	})
    64  }
    65  
    66  func assertParse(t *testing.T, vrw types.ValueReadWriter, code string, expected types.Value) {
    67  	t.Run(code, func(t *testing.T) {
    68  		actual, err := Parse(context.Background(), vrw, code)
    69  		if !assert.NoError(t, err) {
    70  			return
    71  		}
    72  		assert.True(t, expected.Equals(actual))
    73  	})
    74  }
    75  
    76  func assertParseError(t *testing.T, code, msg string) {
    77  	t.Run(code, func(t *testing.T) {
    78  		vrw := newTestValueStore()
    79  		p := New(vrw, strings.NewReader(code), ParserOptions{
    80  			Filename: "example",
    81  		})
    82  		err := catchSyntaxError(func() {
    83  			p.parseValue(context.Background())
    84  		})
    85  		if assert.Error(t, err) {
    86  			assert.Equal(t, msg, err.Error())
    87  		}
    88  	})
    89  }
    90  
    91  func TestSimpleTypes(t *testing.T) {
    92  	assertParseType(t, "Blob", types.PrimitiveTypeMap[types.BlobKind])
    93  	assertParseType(t, "Bool", types.PrimitiveTypeMap[types.BoolKind])
    94  	assertParseType(t, "Float", types.PrimitiveTypeMap[types.FloatKind])
    95  	assertParseType(t, "String", types.PrimitiveTypeMap[types.StringKind])
    96  	assertParseType(t, "Value", types.PrimitiveTypeMap[types.ValueKind])
    97  	assertParseType(t, "Type", types.PrimitiveTypeMap[types.TypeKind])
    98  }
    99  
   100  func TestWhitespace(t *testing.T) {
   101  	for _, r := range " \t\n\r" {
   102  		assertParseType(t, string(r)+"Blob", types.PrimitiveTypeMap[types.BlobKind])
   103  		assertParseType(t, "Blob"+string(r), types.PrimitiveTypeMap[types.BlobKind])
   104  	}
   105  }
   106  
   107  func TestComments(t *testing.T) {
   108  	assertParseType(t, "/* */Blob", types.PrimitiveTypeMap[types.BlobKind])
   109  	assertParseType(t, "Blob/* */", types.PrimitiveTypeMap[types.BlobKind])
   110  	assertParseType(t, "Blob//", types.PrimitiveTypeMap[types.BlobKind])
   111  	assertParseType(t, "//\nBlob", types.PrimitiveTypeMap[types.BlobKind])
   112  }
   113  
   114  func TestCompoundTypes(t *testing.T) {
   115  	assertParseType(t, "List<>", mustType(types.MakeListType(mustType(types.MakeUnionType()))))
   116  	assertParseType(t, "List<Bool>", mustType(types.MakeListType(types.PrimitiveTypeMap[types.BoolKind])))
   117  	assertParseError(t, "List<Bool, Float>", `Unexpected token ",", expected ">", example:1:11`)
   118  	assertParseError(t, "List<Bool", `Unexpected token EOF, expected ">", example:1:10`)
   119  	assertParseError(t, "List<", `Unexpected token EOF, expected Ident, example:1:6`)
   120  	assertParseError(t, "List", `Unexpected token EOF, expected "<", example:1:5`)
   121  
   122  	assertParseType(t, "Set<>", mustType(types.MakeSetType(mustType(types.MakeUnionType()))))
   123  	assertParseType(t, "Set<Bool>", mustType(types.MakeSetType(types.PrimitiveTypeMap[types.BoolKind])))
   124  	assertParseError(t, "Set<Bool, Float>", `Unexpected token ",", expected ">", example:1:10`)
   125  	assertParseError(t, "Set<Bool", `Unexpected token EOF, expected ">", example:1:9`)
   126  	assertParseError(t, "Set<", `Unexpected token EOF, expected Ident, example:1:5`)
   127  	assertParseError(t, "Set", `Unexpected token EOF, expected "<", example:1:4`)
   128  
   129  	assertParseError(t, "Ref<>", `Unexpected token ">", expected Ident, example:1:6`)
   130  	assertParseType(t, "Ref<Bool>", mustType(types.MakeRefType(types.PrimitiveTypeMap[types.BoolKind])))
   131  	assertParseError(t, "Ref<Float, Bool>", `Unexpected token ",", expected ">", example:1:11`)
   132  	assertParseError(t, "Ref<Float", `Unexpected token EOF, expected ">", example:1:10`)
   133  	assertParseError(t, "Ref<", `Unexpected token EOF, expected Ident, example:1:5`)
   134  	assertParseError(t, "Ref", `Unexpected token EOF, expected "<", example:1:4`)
   135  
   136  	// Cannot use Equals on unresolved cycles.
   137  	ct := MustParseType("Cycle<Abc>")
   138  	assert.Equal(t, ct, types.MakeCycleType("Abc"))
   139  
   140  	assertParseError(t, "Cycle<-123>", `Unexpected token "-", expected Ident, example:1:8`)
   141  	assertParseError(t, "Cycle<12.3>", `Unexpected token Float, expected Ident, example:1:11`)
   142  	assertParseError(t, "Cycle<>", `Unexpected token ">", expected Ident, example:1:8`)
   143  	assertParseError(t, "Cycle<", `Unexpected token EOF, expected Ident, example:1:7`)
   144  	assertParseError(t, "Cycle", `Unexpected token EOF, expected "<", example:1:6`)
   145  
   146  	assertParseType(t, "Map<>", mustType(types.MakeMapType(mustType(types.MakeUnionType()), mustType(types.MakeUnionType()))))
   147  	assertParseType(t, "Map<Bool, String>", mustType(types.MakeMapType(types.PrimitiveTypeMap[types.BoolKind], types.PrimitiveTypeMap[types.StringKind])))
   148  	assertParseError(t, "Map<Bool,>", `Unexpected token ">", expected Ident, example:1:11`)
   149  	assertParseError(t, "Map<,Bool>", `Unexpected token ",", expected Ident, example:1:6`)
   150  	assertParseError(t, "Map<,>", `Unexpected token ",", expected Ident, example:1:6`)
   151  	assertParseError(t, "Map<Bool,Bool", `Unexpected token EOF, expected ">", example:1:14`)
   152  	assertParseError(t, "Map<Bool,", `Unexpected token EOF, expected Ident, example:1:10`)
   153  	assertParseError(t, "Map<Bool", `Unexpected token EOF, expected ",", example:1:9`)
   154  	assertParseError(t, "Map<", `Unexpected token EOF, expected Ident, example:1:5`)
   155  	assertParseError(t, "Map", `Unexpected token EOF, expected "<", example:1:4`)
   156  }
   157  
   158  func TestStructTypes(t *testing.T) {
   159  	assertParseType(t, "Struct {}", mustType(types.MakeStructTypeFromFields("", types.FieldMap{})))
   160  	assertParseType(t, "Struct S {}", mustType(types.MakeStructTypeFromFields("S", types.FieldMap{})))
   161  
   162  	assertParseType(t, `Struct S {
   163                  x: Float
   164          }`, mustType(types.MakeStructTypeFromFields("S", types.FieldMap{"x": types.PrimitiveTypeMap[types.FloatKind]})))
   165  
   166  	assertParseType(t, `Struct S {
   167  	        x: Float,
   168  	}`, mustType(types.MakeStructTypeFromFields("S", types.FieldMap{"x": types.PrimitiveTypeMap[types.FloatKind]})))
   169  
   170  	assertParseType(t, `Struct S {
   171  	        x: Float,
   172  	        y: String
   173  	}`, mustType(types.MakeStructTypeFromFields("S", types.FieldMap{"x": types.PrimitiveTypeMap[types.FloatKind], "y": types.PrimitiveTypeMap[types.StringKind]})))
   174  
   175  	assertParseType(t, `Struct S {
   176  	        x: Float,
   177  	        y: String,
   178  	}`, mustType(types.MakeStructTypeFromFields("S", types.FieldMap{"x": types.PrimitiveTypeMap[types.FloatKind], "y": types.PrimitiveTypeMap[types.StringKind]})))
   179  
   180  	assertParseType(t, `Struct S {
   181  	        x: Float,
   182  	        y: Struct {
   183  	                z: String,
   184  	        },
   185  	}`, mustType(types.MakeStructTypeFromFields("S", types.FieldMap{
   186  		"x": types.PrimitiveTypeMap[types.FloatKind],
   187  		"y": mustType(types.MakeStructTypeFromFields("", types.FieldMap{"z": types.PrimitiveTypeMap[types.StringKind]})),
   188  	})))
   189  
   190  	assertParseType(t, `Struct S {
   191                  x?: Float,
   192                  y: String,
   193          }`, mustType(types.MakeStructType("S",
   194  		types.StructField{Name: "x", Type: types.PrimitiveTypeMap[types.FloatKind], Optional: true},
   195  		types.StructField{Name: "y", Type: types.PrimitiveTypeMap[types.StringKind], Optional: false},
   196  	)))
   197  
   198  	assertParseError(t, `Struct S {
   199  	        x: Float
   200  	        y: String
   201  	}`, `Unexpected token Ident, expected "}", example:3:11`)
   202  
   203  	assertParseError(t, `Struct S {,}`, `Unexpected token ",", expected Ident, example:1:12`)
   204  	assertParseError(t, `Struct S {`, `Unexpected token EOF, expected Ident, example:1:11`)
   205  	assertParseError(t, `Struct S { x }`, `Unexpected token "}", expected ":", example:1:15`)
   206  	assertParseError(t, `Struct S { x`, `Unexpected token EOF, expected ":", example:1:13`)
   207  	assertParseError(t, `Struct S { x: }`, `Unexpected token "}", expected Ident, example:1:16`)
   208  	assertParseError(t, `Struct S { x: `, `Unexpected token EOF, expected Ident, example:1:15`)
   209  	assertParseError(t, `Struct S { x?: `, `Unexpected token EOF, expected Ident, example:1:16`)
   210  	assertParseError(t, `Struct S { x? `, `Unexpected token EOF, expected ":", example:1:15`)
   211  	assertParseError(t, `Struct S { x? Bool`, `Unexpected token Ident, expected ":", example:1:19`)
   212  	assertParseError(t, `Struct S { x: Bool`, `Unexpected token EOF, expected "}", example:1:19`)
   213  	assertParseError(t, `Struct S { x: Bool,`, `Unexpected token EOF, expected Ident, example:1:20`)
   214  	assertParseError(t, `Struct S { x: Bool,,`, `Unexpected token ",", expected Ident, example:1:21`)
   215  
   216  	assertParseError(t, `Struct S {`, `Unexpected token EOF, expected Ident, example:1:11`)
   217  	assertParseError(t, `Struct S `, `Unexpected token EOF, expected "{", example:1:10`)
   218  	assertParseError(t, `Struct {`, `Unexpected token EOF, expected Ident, example:1:9`)
   219  	assertParseError(t, `Struct`, `Unexpected token EOF, expected "{", example:1:7`)
   220  }
   221  
   222  func TestUnionTypes(t *testing.T) {
   223  	assertParseType(t, "Blob | Bool", mustType(types.MakeUnionType(types.PrimitiveTypeMap[types.BlobKind], types.PrimitiveTypeMap[types.BoolKind])))
   224  	assertParseType(t, "Bool | Float | String", mustType(types.MakeUnionType(types.PrimitiveTypeMap[types.BoolKind], types.PrimitiveTypeMap[types.FloatKind], types.PrimitiveTypeMap[types.StringKind])))
   225  	assertParseType(t, "List<Bool | Float>", mustType(types.MakeListType(mustType(types.MakeUnionType(types.PrimitiveTypeMap[types.BoolKind], types.PrimitiveTypeMap[types.FloatKind])))))
   226  	assertParseType(t, "Map<Bool | Float, Bool | Float>",
   227  		mustType(types.MakeMapType(
   228  			mustType(types.MakeUnionType(types.PrimitiveTypeMap[types.BoolKind], types.PrimitiveTypeMap[types.FloatKind])),
   229  			mustType(types.MakeUnionType(types.PrimitiveTypeMap[types.BoolKind], types.PrimitiveTypeMap[types.FloatKind])),
   230  		)),
   231  	)
   232  	assertParseType(t, `Struct S {
   233                  x: Float | Bool
   234                  }`, mustType(types.MakeStructTypeFromFields("S", types.FieldMap{
   235  		"x": mustType(types.MakeUnionType(types.PrimitiveTypeMap[types.BoolKind], types.PrimitiveTypeMap[types.FloatKind])),
   236  	})))
   237  	assertParseType(t, `Struct S {
   238                  x: Float | Bool,
   239                  y: String
   240          }`, mustType(types.MakeStructTypeFromFields("S", types.FieldMap{
   241  		"x": mustType(types.MakeUnionType(types.PrimitiveTypeMap[types.BoolKind], types.PrimitiveTypeMap[types.FloatKind])),
   242  		"y": types.PrimitiveTypeMap[types.StringKind],
   243  	})))
   244  
   245  	assertParseError(t, "Bool |", "Unexpected token EOF, expected Ident, example:1:7")
   246  	assertParseError(t, "Bool | Float |", "Unexpected token EOF, expected Ident, example:1:15")
   247  	assertParseError(t, "Bool | | ", `Unexpected token "|", expected Ident, example:1:9`)
   248  	assertParseError(t, "", `Unexpected token EOF, example:1:1`)
   249  }
   250  
   251  func TestValuePrimitives(t *testing.T) {
   252  	vs := newTestValueStore()
   253  	assertParse(t, vs, "Float", types.PrimitiveTypeMap[types.FloatKind])
   254  	assertParse(t, vs, "Float | String", mustType(types.MakeUnionType(types.PrimitiveTypeMap[types.FloatKind], types.PrimitiveTypeMap[types.StringKind])))
   255  
   256  	assertParse(t, vs, "true", types.Bool(true))
   257  	assertParse(t, vs, "false", types.Bool(false))
   258  
   259  	assertParse(t, vs, "0", types.Float(0))
   260  	assertParse(t, vs, "1", types.Float(1))
   261  	assertParse(t, vs, "1.1", types.Float(1.1))
   262  	assertParse(t, vs, "1.1e1", types.Float(1.1e1))
   263  	assertParse(t, vs, "1e1", types.Float(1e1))
   264  	assertParse(t, vs, "1e-1", types.Float(1e-1))
   265  	assertParse(t, vs, "1e+1", types.Float(1e+1))
   266  
   267  	assertParse(t, vs, "+0", types.Float(0))
   268  	assertParse(t, vs, "+1", types.Float(1))
   269  	assertParse(t, vs, "+1.1", types.Float(1.1))
   270  	assertParse(t, vs, "+1.1e1", types.Float(1.1e1))
   271  	assertParse(t, vs, "+1e1", types.Float(1e1))
   272  	assertParse(t, vs, "+1e-1", types.Float(1e-1))
   273  	assertParse(t, vs, "+1e+1", types.Float(1e+1))
   274  
   275  	assertParse(t, vs, "-0", types.Float(-0))
   276  	assertParse(t, vs, "-1", types.Float(-1))
   277  	assertParse(t, vs, "-1.1", types.Float(-1.1))
   278  	assertParse(t, vs, "-1.1e1", types.Float(-1.1e1))
   279  	assertParse(t, vs, "-1e1", types.Float(-1e1))
   280  	assertParse(t, vs, "-1e-1", types.Float(-1e-1))
   281  	assertParse(t, vs, "-1e+1", types.Float(-1e+1))
   282  
   283  	assertParse(t, vs, `"a"`, types.String("a"))
   284  	assertParse(t, vs, `""`, types.String(""))
   285  	assertParse(t, vs, `"\""`, types.String("\""))
   286  	assertParseError(t, `"\"`, "Invalid string \"\\\", example:1:4")
   287  	assertParseError(t, `"abc`, "Invalid string \"abc, example:1:5")
   288  	assertParseError(t, `"`, "Invalid string \", example:1:2")
   289  	assertParseError(t, `"
   290  "`, "Invalid string \"\n, example:2:1")
   291  
   292  	assertParseError(t, "`", "Unexpected token \"`\", example:1:2")
   293  }
   294  
   295  func TestValueList(t *testing.T) {
   296  	vs := newTestValueStore()
   297  	assertParse(t, vs, "[]", mustValue(types.NewList(context.Background(), vs)))
   298  
   299  	assertParse(t, vs, "[42]", mustValue(types.NewList(context.Background(), vs, types.Float(42))))
   300  	assertParse(t, vs, "[42,]", mustValue(types.NewList(context.Background(), vs, types.Float(42))))
   301  
   302  	assertParseError(t, "[", "Unexpected token EOF, example:1:2")
   303  	assertParseError(t, "[,", "Unexpected token \",\", example:1:3")
   304  	assertParseError(t, "[42", "Unexpected token EOF, expected \"]\", example:1:4")
   305  	assertParseError(t, "[42,", "Unexpected token EOF, example:1:5")
   306  	assertParseError(t, "[,]", "Unexpected token \",\", example:1:3")
   307  
   308  	assertParse(t, vs, `[42,
   309                  Bool,
   310          ]`, mustValue(types.NewList(context.Background(), vs, types.Float(42), types.PrimitiveTypeMap[types.BoolKind])))
   311  	assertParse(t, vs, `[42,
   312                  Bool
   313          ]`, mustValue(types.NewList(context.Background(), vs, types.Float(42), types.PrimitiveTypeMap[types.BoolKind])))
   314  }
   315  
   316  func TestValueSet(t *testing.T) {
   317  	vs := newTestValueStore()
   318  	assertParse(t, vs, "set {}", mustValue(types.NewSet(context.Background(), vs)))
   319  
   320  	assertParse(t, vs, "set {42}", mustValue(types.NewSet(context.Background(), vs, types.Float(42))))
   321  	assertParse(t, vs, "set {42,}", mustValue(types.NewSet(context.Background(), vs, types.Float(42))))
   322  
   323  	assertParseError(t, "set", "Unexpected token EOF, expected \"{\", example:1:4")
   324  	assertParseError(t, "set {", "Unexpected token EOF, example:1:6")
   325  	assertParseError(t, "set {,", "Unexpected token \",\", example:1:7")
   326  	assertParseError(t, "set {42", "Unexpected token EOF, expected \"}\", example:1:8")
   327  	assertParseError(t, "set {42,", "Unexpected token EOF, example:1:9")
   328  	assertParseError(t, "set {,}", "Unexpected token \",\", example:1:7")
   329  
   330  	assertParse(t, vs, `set {42,
   331                  Bool,
   332          }`, mustValue(types.NewSet(context.Background(), vs, types.Float(42), types.PrimitiveTypeMap[types.BoolKind])))
   333  	assertParse(t, vs, `set {42,
   334                  Bool
   335          }`, mustValue(types.NewSet(context.Background(), vs, types.Float(42), types.PrimitiveTypeMap[types.BoolKind])))
   336  }
   337  
   338  func TestValueMap(t *testing.T) {
   339  	vs := newTestValueStore()
   340  	assertParse(t, vs, "map {}", mustValue(types.NewMap(context.Background(), vs)))
   341  
   342  	assertParse(t, vs, "map {42: true}", mustValue(types.NewMap(context.Background(), vs, types.Float(42), types.Bool(true))))
   343  	assertParse(t, vs, "map {42: true,}", mustValue(types.NewMap(context.Background(), vs, types.Float(42), types.Bool(true))))
   344  
   345  	assertParseError(t, "map", "Unexpected token EOF, expected \"{\", example:1:4")
   346  	assertParseError(t, "map {", "Unexpected token EOF, example:1:6")
   347  	assertParseError(t, "map {,", "Unexpected token \",\", example:1:7")
   348  	assertParseError(t, "map {42", "Unexpected token EOF, expected \":\", example:1:8")
   349  	assertParseError(t, "map {42,", "Unexpected token \",\", expected \":\", example:1:9")
   350  	assertParseError(t, "map {42:", "Unexpected token EOF, example:1:9")
   351  	assertParseError(t, "map {42: true", "Unexpected token EOF, expected \"}\", example:1:14")
   352  	assertParseError(t, "map {,}", "Unexpected token \",\", example:1:7")
   353  
   354  	assertParse(t, vs, `map {42:
   355                  Bool,
   356          }`, mustValue(types.NewMap(context.Background(), vs, types.Float(42), types.PrimitiveTypeMap[types.BoolKind])))
   357  	assertParse(t, vs, `map {42:
   358                  Bool
   359          }`, mustValue(types.NewMap(context.Background(), vs, types.Float(42), types.PrimitiveTypeMap[types.BoolKind])))
   360  }
   361  
   362  func TestValueType(t *testing.T) {
   363  	vs := newTestValueStore()
   364  	assertParse(t, vs, "Bool", types.PrimitiveTypeMap[types.BoolKind])
   365  	assertParse(t, vs, "Float", types.PrimitiveTypeMap[types.FloatKind])
   366  	assertParse(t, vs, "String", types.PrimitiveTypeMap[types.StringKind])
   367  }
   368  
   369  func TestValueStruct(t *testing.T) {
   370  	vs := newTestValueStore()
   371  	assertParse(t, vs, "struct {}", mustValue(types.NewStruct(types.Format_7_18, "", nil)))
   372  	assertParseError(t, "struct", "Unexpected token EOF, expected \"{\", example:1:7")
   373  	assertParseError(t, "struct {", "Unexpected token EOF, expected Ident, example:1:9")
   374  
   375  	assertParse(t, vs, "struct name {}", mustValue(types.NewStruct(types.Format_7_18, "name", nil)))
   376  	assertParseError(t, "struct name", "Unexpected token EOF, expected \"{\", example:1:12")
   377  	assertParseError(t, "struct name {", "Unexpected token EOF, expected Ident, example:1:14")
   378  
   379  	assertParse(t, vs, "struct name {a: 42}", mustValue(types.NewStruct(types.Format_7_18, "name", types.StructData{"a": types.Float(42)})))
   380  	assertParse(t, vs, "struct name {a: 42,}", mustValue(types.NewStruct(types.Format_7_18, "name", types.StructData{"a": types.Float(42)})))
   381  	assertParseError(t, "struct name {a", "Unexpected token EOF, expected \":\", example:1:15")
   382  	assertParseError(t, "struct name {a: ", "Unexpected token EOF, example:1:17")
   383  	assertParseError(t, "struct name {a,", "Unexpected token \",\", expected \":\", example:1:16")
   384  	assertParseError(t, "struct name {a}", "Unexpected token \"}\", expected \":\", example:1:16")
   385  	assertParseError(t, "struct name {a: 42", "Unexpected token EOF, expected \"}\", example:1:19")
   386  	assertParseError(t, "struct name {a: 42,", "Unexpected token EOF, expected Ident, example:1:20")
   387  	assertParseError(t, "struct name {a:}", "Unexpected token \"}\", example:1:17")
   388  
   389  	assertParse(t, vs, "struct name {b: 42, a: true}", mustValue(types.NewStruct(types.Format_7_18, "name", types.StructData{"b": types.Float(42), "a": types.Bool(true)})))
   390  	assertParse(t, vs, `struct name {
   391                  b: 42,
   392                  a: true,
   393          }`, mustValue(types.NewStruct(types.Format_7_18, "name", types.StructData{"b": types.Float(42), "a": types.Bool(true)})))
   394  
   395  	assertParse(t, vs, "struct name {a: Struct {}}", mustValue(types.NewStruct(types.Format_7_18, "name", types.StructData{"a": mustType(types.MakeStructType(""))})))
   396  }
   397  
   398  func TestValueBlob(t *testing.T) {
   399  	vs := newTestValueStore()
   400  
   401  	test := func(code string, bs ...byte) {
   402  		assertParse(t, vs, code, mustValue(types.NewBlob(context.Background(), vs, bytes.NewBuffer(bs))))
   403  	}
   404  
   405  	test("blob {}")
   406  	test("blob {// comment\n}")
   407  	test("blob {10}", 0x10)
   408  	test("blob {10/* comment */}", 0x10)
   409  	test("blob {0000ff}", 0, 0, 0xff)
   410  	test("blob {00 00 ff}", 0, 0, 0xff)
   411  	test("blob { 00\n00\nff }", 0, 0, 0xff)
   412  	test("blob { ffffffff ffffffff ffffffff ffffffff}",
   413  		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   414  		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   415  	)
   416  	test("blob { ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff}",
   417  		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   418  		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   419  		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   420  		0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
   421  	)
   422  
   423  	assertParseError(t, "blob", "Unexpected token EOF, expected \"{\", example:1:5")
   424  	assertParseError(t, "blob {", "Unexpected token EOF, example:1:7")
   425  	assertParseError(t, "blob { 00", "Unexpected token EOF, example:1:10")
   426  	assertParseError(t, "blob {hh}", "Invalid blob \"hh\", example:1:9")
   427  	assertParseError(t, "blob {0}", "Invalid blob \"0\", example:1:8")
   428  	assertParseError(t, "blob {00 0}", "Invalid blob \"0\", example:1:11")
   429  	assertParseError(t, "blob {ff 0 0}", "Invalid blob \"0\", example:1:11")
   430  
   431  }
   432  
   433  func TestRoundTrips(t *testing.T) {
   434  	vs := newTestValueStore()
   435  
   436  	test := func(v types.Value) {
   437  		code := mustString(types.EncodedValue(context.Background(), v))
   438  		assertParse(t, vs, code, v)
   439  	}
   440  
   441  	test(types.Float(0))
   442  	test(types.Float(42))
   443  	test(types.Float(-0))
   444  	test(types.Float(-42))
   445  	test(types.Float(0.05))
   446  	test(types.Float(-0.05))
   447  	test(types.Float(1e50))
   448  	test(types.Float(-1e50))
   449  
   450  	test(types.Bool(true))
   451  	test(types.Bool(false))
   452  
   453  	test(types.String(""))
   454  	test(types.String("a"))
   455  	test(types.String("\""))
   456  	test(types.String("'"))
   457  	test(types.String("`"))
   458  
   459  	test(mustValue(types.NewEmptyBlob(vs)))
   460  	test(mustValue(types.NewBlob(context.Background(), vs, bytes.NewBufferString("abc"))))
   461  
   462  	test(mustValue(types.NewList(context.Background(), vs)))
   463  	test(mustValue(types.NewList(context.Background(), vs, types.Float(42), types.Bool(true), types.String("abc"))))
   464  
   465  	test(mustValue(types.NewSet(context.Background(), vs)))
   466  	test(mustValue(types.NewSet(context.Background(), vs, types.Float(42), types.Bool(true), types.String("abc"))))
   467  
   468  	test(mustValue(types.NewMap(context.Background(), vs)))
   469  	test(mustValue(types.NewMap(context.Background(), vs, types.Float(42), types.Bool(true), types.String("abc"), mustValue(types.NewMap(context.Background(), vs)))))
   470  
   471  	test(mustValue(types.NewStruct(types.Format_7_18, "", nil)))
   472  	test(mustValue(types.NewStruct(types.Format_7_18, "Float", nil)))
   473  	test(mustValue(types.NewStruct(types.Format_7_18, "Float", types.StructData{
   474  		"Float": types.PrimitiveTypeMap[types.FloatKind],
   475  	})))
   476  
   477  	test(mustType(types.MakeStructType("S", types.StructField{
   478  		Name: "cycle", Type: types.MakeCycleType("S"), Optional: true,
   479  	})))
   480  }