| 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()) |
| } |
| }) |
| } |
| } |