package json import ( "bytes" "fmt" "reflect" "testing" "github.com/hashicorp/hcl/v2" ) func TestScan(t *testing.T) { tests := []struct { Input string Want []token }{ { ``, []token{ { Type: tokenEOF, Range: hcl.Range{ Start: hcl.Pos{ Byte: 0, Line: 1, Column: 1, }, End: hcl.Pos{ Byte: 0, Line: 1, Column: 1, }, }, }, }, }, { ` `, []token{ { Type: tokenEOF, Range: hcl.Range{ Start: hcl.Pos{ Byte: 3, Line: 1, Column: 4, }, End: hcl.Pos{ Byte: 3, Line: 1, Column: 4, }, }, }, }, }, { `{}`, []token{ { Type: tokenBraceO, Bytes: []byte(`{`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 0, Line: 1, Column: 1, }, End: hcl.Pos{ Byte: 1, Line: 1, Column: 2, }, }, }, { Type: tokenBraceC, Bytes: []byte(`}`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 1, Line: 1, Column: 2, }, End: hcl.Pos{ Byte: 2, Line: 1, Column: 3, }, }, }, { Type: tokenEOF, Range: hcl.Range{ Start: hcl.Pos{ Byte: 2, Line: 1, Column: 3, }, End: hcl.Pos{ Byte: 2, Line: 1, Column: 3, }, }, }, }, }, { `][`, []token{ { Type: tokenBrackC, Bytes: []byte(`]`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 0, Line: 1, Column: 1, }, End: hcl.Pos{ Byte: 1, Line: 1, Column: 2, }, }, }, { Type: tokenBrackO, Bytes: []byte(`[`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 1, Line: 1, Column: 2, }, End: hcl.Pos{ Byte: 2, Line: 1, Column: 3, }, }, }, { Type: tokenEOF, Range: hcl.Range{ Start: hcl.Pos{ Byte: 2, Line: 1, Column: 3, }, End: hcl.Pos{ Byte: 2, Line: 1, Column: 3, }, }, }, }, }, { `:,`, []token{ { Type: tokenColon, Bytes: []byte(`:`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 0, Line: 1, Column: 1, }, End: hcl.Pos{ Byte: 1, Line: 1, Column: 2, }, }, }, { Type: tokenComma, Bytes: []byte(`,`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 1, Line: 1, Column: 2, }, End: hcl.Pos{ Byte: 2, Line: 1, Column: 3, }, }, }, { Type: tokenEOF, Range: hcl.Range{ Start: hcl.Pos{ Byte: 2, Line: 1, Column: 3, }, End: hcl.Pos{ Byte: 2, Line: 1, Column: 3, }, }, }, }, }, { `1`, []token{ { Type: tokenNumber, Bytes: []byte(`1`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 0, Line: 1, Column: 1, }, End: hcl.Pos{ Byte: 1, Line: 1, Column: 2, }, }, }, { Type: tokenEOF, Range: hcl.Range{ Start: hcl.Pos{ Byte: 1, Line: 1, Column: 2, }, End: hcl.Pos{ Byte: 1, Line: 1, Column: 2, }, }, }, }, }, { ` 1`, []token{ { Type: tokenNumber, Bytes: []byte(`1`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 2, Line: 1, Column: 3, }, End: hcl.Pos{ Byte: 3, Line: 1, Column: 4, }, }, }, { Type: tokenEOF, Range: hcl.Range{ Start: hcl.Pos{ Byte: 3, Line: 1, Column: 4, }, End: hcl.Pos{ Byte: 3, Line: 1, Column: 4, }, }, }, }, }, { ` 12`, []token{ { Type: tokenNumber, Bytes: []byte(`12`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 2, Line: 1, Column: 3, }, End: hcl.Pos{ Byte: 4, Line: 1, Column: 5, }, }, }, { Type: tokenEOF, Range: hcl.Range{ Start: hcl.Pos{ Byte: 4, Line: 1, Column: 5, }, End: hcl.Pos{ Byte: 4, Line: 1, Column: 5, }, }, }, }, }, { `1 2`, []token{ { Type: tokenNumber, Bytes: []byte(`1`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 0, Line: 1, Column: 1, }, End: hcl.Pos{ Byte: 1, Line: 1, Column: 2, }, }, }, { Type: tokenNumber, Bytes: []byte(`2`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 2, Line: 1, Column: 3, }, End: hcl.Pos{ Byte: 3, Line: 1, Column: 4, }, }, }, { Type: tokenEOF, Range: hcl.Range{ Start: hcl.Pos{ Byte: 3, Line: 1, Column: 4, }, End: hcl.Pos{ Byte: 3, Line: 1, Column: 4, }, }, }, }, }, { "\n1\n 2", []token{ { Type: tokenNumber, Bytes: []byte(`1`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 1, Line: 2, Column: 1, }, End: hcl.Pos{ Byte: 2, Line: 2, Column: 2, }, }, }, { Type: tokenNumber, Bytes: []byte(`2`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 4, Line: 3, Column: 2, }, End: hcl.Pos{ Byte: 5, Line: 3, Column: 3, }, }, }, { Type: tokenEOF, Range: hcl.Range{ Start: hcl.Pos{ Byte: 5, Line: 3, Column: 3, }, End: hcl.Pos{ Byte: 5, Line: 3, Column: 3, }, }, }, }, }, { `-1 2.5`, []token{ { Type: tokenNumber, Bytes: []byte(`-1`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 0, Line: 1, Column: 1, }, End: hcl.Pos{ Byte: 2, Line: 1, Column: 3, }, }, }, { Type: tokenNumber, Bytes: []byte(`2.5`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 3, Line: 1, Column: 4, }, End: hcl.Pos{ Byte: 6, Line: 1, Column: 7, }, }, }, { Type: tokenEOF, Range: hcl.Range{ Start: hcl.Pos{ Byte: 6, Line: 1, Column: 7, }, End: hcl.Pos{ Byte: 6, Line: 1, Column: 7, }, }, }, }, }, { `true`, []token{ { Type: tokenKeyword, Bytes: []byte(`true`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 0, Line: 1, Column: 1, }, End: hcl.Pos{ Byte: 4, Line: 1, Column: 5, }, }, }, { Type: tokenEOF, Range: hcl.Range{ Start: hcl.Pos{ Byte: 4, Line: 1, Column: 5, }, End: hcl.Pos{ Byte: 4, Line: 1, Column: 5, }, }, }, }, }, { `[true]`, []token{ { Type: tokenBrackO, Bytes: []byte(`[`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 0, Line: 1, Column: 1, }, End: hcl.Pos{ Byte: 1, Line: 1, Column: 2, }, }, }, { Type: tokenKeyword, Bytes: []byte(`true`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 1, Line: 1, Column: 2, }, End: hcl.Pos{ Byte: 5, Line: 1, Column: 6, }, }, }, { Type: tokenBrackC, Bytes: []byte(`]`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 5, Line: 1, Column: 6, }, End: hcl.Pos{ Byte: 6, Line: 1, Column: 7, }, }, }, { Type: tokenEOF, Range: hcl.Range{ Start: hcl.Pos{ Byte: 6, Line: 1, Column: 7, }, End: hcl.Pos{ Byte: 6, Line: 1, Column: 7, }, }, }, }, }, { `""`, []token{ { Type: tokenString, Bytes: []byte(`""`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 0, Line: 1, Column: 1, }, End: hcl.Pos{ Byte: 2, Line: 1, Column: 3, }, }, }, { Type: tokenEOF, Range: hcl.Range{ Start: hcl.Pos{ Byte: 2, Line: 1, Column: 3, }, End: hcl.Pos{ Byte: 2, Line: 1, Column: 3, }, }, }, }, }, { `"hello"`, []token{ { Type: tokenString, Bytes: []byte(`"hello"`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 0, Line: 1, Column: 1, }, End: hcl.Pos{ Byte: 7, Line: 1, Column: 8, }, }, }, { Type: tokenEOF, Range: hcl.Range{ Start: hcl.Pos{ Byte: 7, Line: 1, Column: 8, }, End: hcl.Pos{ Byte: 7, Line: 1, Column: 8, }, }, }, }, }, { `"he\"llo"`, []token{ { Type: tokenString, Bytes: []byte(`"he\"llo"`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 0, Line: 1, Column: 1, }, End: hcl.Pos{ Byte: 9, Line: 1, Column: 10, }, }, }, { Type: tokenEOF, Range: hcl.Range{ Start: hcl.Pos{ Byte: 9, Line: 1, Column: 10, }, End: hcl.Pos{ Byte: 9, Line: 1, Column: 10, }, }, }, }, }, { `"hello\\" 1`, []token{ { Type: tokenString, Bytes: []byte(`"hello\\"`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 0, Line: 1, Column: 1, }, End: hcl.Pos{ Byte: 9, Line: 1, Column: 10, }, }, }, { Type: tokenNumber, Bytes: []byte(`1`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 10, Line: 1, Column: 11, }, End: hcl.Pos{ Byte: 11, Line: 1, Column: 12, }, }, }, { Type: tokenEOF, Range: hcl.Range{ Start: hcl.Pos{ Byte: 11, Line: 1, Column: 12, }, End: hcl.Pos{ Byte: 11, Line: 1, Column: 12, }, }, }, }, }, { `"🇬🇧"`, []token{ { Type: tokenString, Bytes: []byte(`"🇬🇧"`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 0, Line: 1, Column: 1, }, End: hcl.Pos{ Byte: 10, Line: 1, Column: 4, }, }, }, { Type: tokenEOF, Range: hcl.Range{ Start: hcl.Pos{ Byte: 10, Line: 1, Column: 4, }, End: hcl.Pos{ Byte: 10, Line: 1, Column: 4, }, }, }, }, }, { `"á́́́́́́́"`, []token{ { Type: tokenString, Bytes: []byte(`"á́́́́́́́"`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 0, Line: 1, Column: 1, }, End: hcl.Pos{ Byte: 19, Line: 1, Column: 4, }, }, }, { Type: tokenEOF, Range: hcl.Range{ Start: hcl.Pos{ Byte: 19, Line: 1, Column: 4, }, End: hcl.Pos{ Byte: 19, Line: 1, Column: 4, }, }, }, }, }, { `&`, []token{ { Type: tokenInvalid, Bytes: []byte(`&`), Range: hcl.Range{ Start: hcl.Pos{ Byte: 0, Line: 1, Column: 1, }, End: hcl.Pos{ Byte: 1, Line: 1, Column: 2, }, }, }, { Type: tokenEOF, Range: hcl.Range{ Start: hcl.Pos{ Byte: 1, Line: 1, Column: 2, }, End: hcl.Pos{ Byte: 1, Line: 1, Column: 2, }, }, }, }, }, } for _, test := range tests { t.Run(test.Input, func(t *testing.T) { buf := []byte(test.Input) start := pos{ Filename: "", Pos: hcl.Pos{ Byte: 0, Line: 1, Column: 1, }, } got := scan(buf, start) if !reflect.DeepEqual(got, test.Want) { errMsg := &bytes.Buffer{} errMsg.WriteString("wrong result\ngot:\n") if len(got) == 0 { errMsg.WriteString(" (empty slice)\n") } for _, tok := range got { fmt.Fprintf(errMsg, " - %#v\n", tok) } errMsg.WriteString("want:\n") if len(test.Want) == 0 { errMsg.WriteString(" (empty slice)\n") } for _, tok := range test.Want { fmt.Fprintf(errMsg, " - %#v\n", tok) } t.Error(errMsg.String()) } }) } }