blob: eb4ea3ed655ff58b3276573133ee22663bf3a4d2 [file] [log] [blame]
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())
}
})
}
}