github.com/hashicorp/hcl/v2@v2.20.0/json/scanner_test.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package json
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  	"reflect"
    10  	"testing"
    11  
    12  	"github.com/hashicorp/hcl/v2"
    13  )
    14  
    15  func TestScan(t *testing.T) {
    16  	tests := []struct {
    17  		Input string
    18  		Want  []token
    19  	}{
    20  		{
    21  			``,
    22  			[]token{
    23  				{
    24  					Type: tokenEOF,
    25  					Range: hcl.Range{
    26  						Start: hcl.Pos{
    27  							Byte:   0,
    28  							Line:   1,
    29  							Column: 1,
    30  						},
    31  						End: hcl.Pos{
    32  							Byte:   0,
    33  							Line:   1,
    34  							Column: 1,
    35  						},
    36  					},
    37  				},
    38  			},
    39  		},
    40  		{
    41  			`   `,
    42  			[]token{
    43  				{
    44  					Type: tokenEOF,
    45  					Range: hcl.Range{
    46  						Start: hcl.Pos{
    47  							Byte:   3,
    48  							Line:   1,
    49  							Column: 4,
    50  						},
    51  						End: hcl.Pos{
    52  							Byte:   3,
    53  							Line:   1,
    54  							Column: 4,
    55  						},
    56  					},
    57  				},
    58  			},
    59  		},
    60  		{
    61  			`{}`,
    62  			[]token{
    63  				{
    64  					Type:  tokenBraceO,
    65  					Bytes: []byte(`{`),
    66  					Range: hcl.Range{
    67  						Start: hcl.Pos{
    68  							Byte:   0,
    69  							Line:   1,
    70  							Column: 1,
    71  						},
    72  						End: hcl.Pos{
    73  							Byte:   1,
    74  							Line:   1,
    75  							Column: 2,
    76  						},
    77  					},
    78  				},
    79  				{
    80  					Type:  tokenBraceC,
    81  					Bytes: []byte(`}`),
    82  					Range: hcl.Range{
    83  						Start: hcl.Pos{
    84  							Byte:   1,
    85  							Line:   1,
    86  							Column: 2,
    87  						},
    88  						End: hcl.Pos{
    89  							Byte:   2,
    90  							Line:   1,
    91  							Column: 3,
    92  						},
    93  					},
    94  				},
    95  				{
    96  					Type: tokenEOF,
    97  					Range: hcl.Range{
    98  						Start: hcl.Pos{
    99  							Byte:   2,
   100  							Line:   1,
   101  							Column: 3,
   102  						},
   103  						End: hcl.Pos{
   104  							Byte:   2,
   105  							Line:   1,
   106  							Column: 3,
   107  						},
   108  					},
   109  				},
   110  			},
   111  		},
   112  		{
   113  			`][`,
   114  			[]token{
   115  				{
   116  					Type:  tokenBrackC,
   117  					Bytes: []byte(`]`),
   118  					Range: hcl.Range{
   119  						Start: hcl.Pos{
   120  							Byte:   0,
   121  							Line:   1,
   122  							Column: 1,
   123  						},
   124  						End: hcl.Pos{
   125  							Byte:   1,
   126  							Line:   1,
   127  							Column: 2,
   128  						},
   129  					},
   130  				},
   131  				{
   132  					Type:  tokenBrackO,
   133  					Bytes: []byte(`[`),
   134  					Range: hcl.Range{
   135  						Start: hcl.Pos{
   136  							Byte:   1,
   137  							Line:   1,
   138  							Column: 2,
   139  						},
   140  						End: hcl.Pos{
   141  							Byte:   2,
   142  							Line:   1,
   143  							Column: 3,
   144  						},
   145  					},
   146  				},
   147  				{
   148  					Type: tokenEOF,
   149  					Range: hcl.Range{
   150  						Start: hcl.Pos{
   151  							Byte:   2,
   152  							Line:   1,
   153  							Column: 3,
   154  						},
   155  						End: hcl.Pos{
   156  							Byte:   2,
   157  							Line:   1,
   158  							Column: 3,
   159  						},
   160  					},
   161  				},
   162  			},
   163  		},
   164  		{
   165  			`:,`,
   166  			[]token{
   167  				{
   168  					Type:  tokenColon,
   169  					Bytes: []byte(`:`),
   170  					Range: hcl.Range{
   171  						Start: hcl.Pos{
   172  							Byte:   0,
   173  							Line:   1,
   174  							Column: 1,
   175  						},
   176  						End: hcl.Pos{
   177  							Byte:   1,
   178  							Line:   1,
   179  							Column: 2,
   180  						},
   181  					},
   182  				},
   183  				{
   184  					Type:  tokenComma,
   185  					Bytes: []byte(`,`),
   186  					Range: hcl.Range{
   187  						Start: hcl.Pos{
   188  							Byte:   1,
   189  							Line:   1,
   190  							Column: 2,
   191  						},
   192  						End: hcl.Pos{
   193  							Byte:   2,
   194  							Line:   1,
   195  							Column: 3,
   196  						},
   197  					},
   198  				},
   199  				{
   200  					Type: tokenEOF,
   201  					Range: hcl.Range{
   202  						Start: hcl.Pos{
   203  							Byte:   2,
   204  							Line:   1,
   205  							Column: 3,
   206  						},
   207  						End: hcl.Pos{
   208  							Byte:   2,
   209  							Line:   1,
   210  							Column: 3,
   211  						},
   212  					},
   213  				},
   214  			},
   215  		},
   216  		{
   217  			`1`,
   218  			[]token{
   219  				{
   220  					Type:  tokenNumber,
   221  					Bytes: []byte(`1`),
   222  					Range: hcl.Range{
   223  						Start: hcl.Pos{
   224  							Byte:   0,
   225  							Line:   1,
   226  							Column: 1,
   227  						},
   228  						End: hcl.Pos{
   229  							Byte:   1,
   230  							Line:   1,
   231  							Column: 2,
   232  						},
   233  					},
   234  				},
   235  				{
   236  					Type: tokenEOF,
   237  					Range: hcl.Range{
   238  						Start: hcl.Pos{
   239  							Byte:   1,
   240  							Line:   1,
   241  							Column: 2,
   242  						},
   243  						End: hcl.Pos{
   244  							Byte:   1,
   245  							Line:   1,
   246  							Column: 2,
   247  						},
   248  					},
   249  				},
   250  			},
   251  		},
   252  		{
   253  			`  1`,
   254  			[]token{
   255  				{
   256  					Type:  tokenNumber,
   257  					Bytes: []byte(`1`),
   258  					Range: hcl.Range{
   259  						Start: hcl.Pos{
   260  							Byte:   2,
   261  							Line:   1,
   262  							Column: 3,
   263  						},
   264  						End: hcl.Pos{
   265  							Byte:   3,
   266  							Line:   1,
   267  							Column: 4,
   268  						},
   269  					},
   270  				},
   271  				{
   272  					Type: tokenEOF,
   273  					Range: hcl.Range{
   274  						Start: hcl.Pos{
   275  							Byte:   3,
   276  							Line:   1,
   277  							Column: 4,
   278  						},
   279  						End: hcl.Pos{
   280  							Byte:   3,
   281  							Line:   1,
   282  							Column: 4,
   283  						},
   284  					},
   285  				},
   286  			},
   287  		},
   288  		{
   289  			`  12`,
   290  			[]token{
   291  				{
   292  					Type:  tokenNumber,
   293  					Bytes: []byte(`12`),
   294  					Range: hcl.Range{
   295  						Start: hcl.Pos{
   296  							Byte:   2,
   297  							Line:   1,
   298  							Column: 3,
   299  						},
   300  						End: hcl.Pos{
   301  							Byte:   4,
   302  							Line:   1,
   303  							Column: 5,
   304  						},
   305  					},
   306  				},
   307  				{
   308  					Type: tokenEOF,
   309  					Range: hcl.Range{
   310  						Start: hcl.Pos{
   311  							Byte:   4,
   312  							Line:   1,
   313  							Column: 5,
   314  						},
   315  						End: hcl.Pos{
   316  							Byte:   4,
   317  							Line:   1,
   318  							Column: 5,
   319  						},
   320  					},
   321  				},
   322  			},
   323  		},
   324  		{
   325  			`1 2`,
   326  			[]token{
   327  				{
   328  					Type:  tokenNumber,
   329  					Bytes: []byte(`1`),
   330  					Range: hcl.Range{
   331  						Start: hcl.Pos{
   332  							Byte:   0,
   333  							Line:   1,
   334  							Column: 1,
   335  						},
   336  						End: hcl.Pos{
   337  							Byte:   1,
   338  							Line:   1,
   339  							Column: 2,
   340  						},
   341  					},
   342  				},
   343  				{
   344  					Type:  tokenNumber,
   345  					Bytes: []byte(`2`),
   346  					Range: hcl.Range{
   347  						Start: hcl.Pos{
   348  							Byte:   2,
   349  							Line:   1,
   350  							Column: 3,
   351  						},
   352  						End: hcl.Pos{
   353  							Byte:   3,
   354  							Line:   1,
   355  							Column: 4,
   356  						},
   357  					},
   358  				},
   359  				{
   360  					Type: tokenEOF,
   361  					Range: hcl.Range{
   362  						Start: hcl.Pos{
   363  							Byte:   3,
   364  							Line:   1,
   365  							Column: 4,
   366  						},
   367  						End: hcl.Pos{
   368  							Byte:   3,
   369  							Line:   1,
   370  							Column: 4,
   371  						},
   372  					},
   373  				},
   374  			},
   375  		},
   376  		{
   377  			"\n1\n 2",
   378  			[]token{
   379  				{
   380  					Type:  tokenNumber,
   381  					Bytes: []byte(`1`),
   382  					Range: hcl.Range{
   383  						Start: hcl.Pos{
   384  							Byte:   1,
   385  							Line:   2,
   386  							Column: 1,
   387  						},
   388  						End: hcl.Pos{
   389  							Byte:   2,
   390  							Line:   2,
   391  							Column: 2,
   392  						},
   393  					},
   394  				},
   395  				{
   396  					Type:  tokenNumber,
   397  					Bytes: []byte(`2`),
   398  					Range: hcl.Range{
   399  						Start: hcl.Pos{
   400  							Byte:   4,
   401  							Line:   3,
   402  							Column: 2,
   403  						},
   404  						End: hcl.Pos{
   405  							Byte:   5,
   406  							Line:   3,
   407  							Column: 3,
   408  						},
   409  					},
   410  				},
   411  				{
   412  					Type: tokenEOF,
   413  					Range: hcl.Range{
   414  						Start: hcl.Pos{
   415  							Byte:   5,
   416  							Line:   3,
   417  							Column: 3,
   418  						},
   419  						End: hcl.Pos{
   420  							Byte:   5,
   421  							Line:   3,
   422  							Column: 3,
   423  						},
   424  					},
   425  				},
   426  			},
   427  		},
   428  		{
   429  			`-1 2.5`,
   430  			[]token{
   431  				{
   432  					Type:  tokenNumber,
   433  					Bytes: []byte(`-1`),
   434  					Range: hcl.Range{
   435  						Start: hcl.Pos{
   436  							Byte:   0,
   437  							Line:   1,
   438  							Column: 1,
   439  						},
   440  						End: hcl.Pos{
   441  							Byte:   2,
   442  							Line:   1,
   443  							Column: 3,
   444  						},
   445  					},
   446  				},
   447  				{
   448  					Type:  tokenNumber,
   449  					Bytes: []byte(`2.5`),
   450  					Range: hcl.Range{
   451  						Start: hcl.Pos{
   452  							Byte:   3,
   453  							Line:   1,
   454  							Column: 4,
   455  						},
   456  						End: hcl.Pos{
   457  							Byte:   6,
   458  							Line:   1,
   459  							Column: 7,
   460  						},
   461  					},
   462  				},
   463  				{
   464  					Type: tokenEOF,
   465  					Range: hcl.Range{
   466  						Start: hcl.Pos{
   467  							Byte:   6,
   468  							Line:   1,
   469  							Column: 7,
   470  						},
   471  						End: hcl.Pos{
   472  							Byte:   6,
   473  							Line:   1,
   474  							Column: 7,
   475  						},
   476  					},
   477  				},
   478  			},
   479  		},
   480  		{
   481  			`true`,
   482  			[]token{
   483  				{
   484  					Type:  tokenKeyword,
   485  					Bytes: []byte(`true`),
   486  					Range: hcl.Range{
   487  						Start: hcl.Pos{
   488  							Byte:   0,
   489  							Line:   1,
   490  							Column: 1,
   491  						},
   492  						End: hcl.Pos{
   493  							Byte:   4,
   494  							Line:   1,
   495  							Column: 5,
   496  						},
   497  					},
   498  				},
   499  				{
   500  					Type: tokenEOF,
   501  					Range: hcl.Range{
   502  						Start: hcl.Pos{
   503  							Byte:   4,
   504  							Line:   1,
   505  							Column: 5,
   506  						},
   507  						End: hcl.Pos{
   508  							Byte:   4,
   509  							Line:   1,
   510  							Column: 5,
   511  						},
   512  					},
   513  				},
   514  			},
   515  		},
   516  		{
   517  			`[true]`,
   518  			[]token{
   519  				{
   520  					Type:  tokenBrackO,
   521  					Bytes: []byte(`[`),
   522  					Range: hcl.Range{
   523  						Start: hcl.Pos{
   524  							Byte:   0,
   525  							Line:   1,
   526  							Column: 1,
   527  						},
   528  						End: hcl.Pos{
   529  							Byte:   1,
   530  							Line:   1,
   531  							Column: 2,
   532  						},
   533  					},
   534  				},
   535  				{
   536  					Type:  tokenKeyword,
   537  					Bytes: []byte(`true`),
   538  					Range: hcl.Range{
   539  						Start: hcl.Pos{
   540  							Byte:   1,
   541  							Line:   1,
   542  							Column: 2,
   543  						},
   544  						End: hcl.Pos{
   545  							Byte:   5,
   546  							Line:   1,
   547  							Column: 6,
   548  						},
   549  					},
   550  				},
   551  				{
   552  					Type:  tokenBrackC,
   553  					Bytes: []byte(`]`),
   554  					Range: hcl.Range{
   555  						Start: hcl.Pos{
   556  							Byte:   5,
   557  							Line:   1,
   558  							Column: 6,
   559  						},
   560  						End: hcl.Pos{
   561  							Byte:   6,
   562  							Line:   1,
   563  							Column: 7,
   564  						},
   565  					},
   566  				},
   567  				{
   568  					Type: tokenEOF,
   569  					Range: hcl.Range{
   570  						Start: hcl.Pos{
   571  							Byte:   6,
   572  							Line:   1,
   573  							Column: 7,
   574  						},
   575  						End: hcl.Pos{
   576  							Byte:   6,
   577  							Line:   1,
   578  							Column: 7,
   579  						},
   580  					},
   581  				},
   582  			},
   583  		},
   584  		{
   585  			`""`,
   586  			[]token{
   587  				{
   588  					Type:  tokenString,
   589  					Bytes: []byte(`""`),
   590  					Range: hcl.Range{
   591  						Start: hcl.Pos{
   592  							Byte:   0,
   593  							Line:   1,
   594  							Column: 1,
   595  						},
   596  						End: hcl.Pos{
   597  							Byte:   2,
   598  							Line:   1,
   599  							Column: 3,
   600  						},
   601  					},
   602  				},
   603  				{
   604  					Type: tokenEOF,
   605  					Range: hcl.Range{
   606  						Start: hcl.Pos{
   607  							Byte:   2,
   608  							Line:   1,
   609  							Column: 3,
   610  						},
   611  						End: hcl.Pos{
   612  							Byte:   2,
   613  							Line:   1,
   614  							Column: 3,
   615  						},
   616  					},
   617  				},
   618  			},
   619  		},
   620  		{
   621  			`"hello"`,
   622  			[]token{
   623  				{
   624  					Type:  tokenString,
   625  					Bytes: []byte(`"hello"`),
   626  					Range: hcl.Range{
   627  						Start: hcl.Pos{
   628  							Byte:   0,
   629  							Line:   1,
   630  							Column: 1,
   631  						},
   632  						End: hcl.Pos{
   633  							Byte:   7,
   634  							Line:   1,
   635  							Column: 8,
   636  						},
   637  					},
   638  				},
   639  				{
   640  					Type: tokenEOF,
   641  					Range: hcl.Range{
   642  						Start: hcl.Pos{
   643  							Byte:   7,
   644  							Line:   1,
   645  							Column: 8,
   646  						},
   647  						End: hcl.Pos{
   648  							Byte:   7,
   649  							Line:   1,
   650  							Column: 8,
   651  						},
   652  					},
   653  				},
   654  			},
   655  		},
   656  		{
   657  			`"he\"llo"`,
   658  			[]token{
   659  				{
   660  					Type:  tokenString,
   661  					Bytes: []byte(`"he\"llo"`),
   662  					Range: hcl.Range{
   663  						Start: hcl.Pos{
   664  							Byte:   0,
   665  							Line:   1,
   666  							Column: 1,
   667  						},
   668  						End: hcl.Pos{
   669  							Byte:   9,
   670  							Line:   1,
   671  							Column: 10,
   672  						},
   673  					},
   674  				},
   675  				{
   676  					Type: tokenEOF,
   677  					Range: hcl.Range{
   678  						Start: hcl.Pos{
   679  							Byte:   9,
   680  							Line:   1,
   681  							Column: 10,
   682  						},
   683  						End: hcl.Pos{
   684  							Byte:   9,
   685  							Line:   1,
   686  							Column: 10,
   687  						},
   688  					},
   689  				},
   690  			},
   691  		},
   692  		{
   693  			`"hello\\" 1`,
   694  			[]token{
   695  				{
   696  					Type:  tokenString,
   697  					Bytes: []byte(`"hello\\"`),
   698  					Range: hcl.Range{
   699  						Start: hcl.Pos{
   700  							Byte:   0,
   701  							Line:   1,
   702  							Column: 1,
   703  						},
   704  						End: hcl.Pos{
   705  							Byte:   9,
   706  							Line:   1,
   707  							Column: 10,
   708  						},
   709  					},
   710  				},
   711  				{
   712  					Type:  tokenNumber,
   713  					Bytes: []byte(`1`),
   714  					Range: hcl.Range{
   715  						Start: hcl.Pos{
   716  							Byte:   10,
   717  							Line:   1,
   718  							Column: 11,
   719  						},
   720  						End: hcl.Pos{
   721  							Byte:   11,
   722  							Line:   1,
   723  							Column: 12,
   724  						},
   725  					},
   726  				},
   727  				{
   728  					Type: tokenEOF,
   729  					Range: hcl.Range{
   730  						Start: hcl.Pos{
   731  							Byte:   11,
   732  							Line:   1,
   733  							Column: 12,
   734  						},
   735  						End: hcl.Pos{
   736  							Byte:   11,
   737  							Line:   1,
   738  							Column: 12,
   739  						},
   740  					},
   741  				},
   742  			},
   743  		},
   744  		{
   745  			`"🇬🇧"`,
   746  			[]token{
   747  				{
   748  					Type:  tokenString,
   749  					Bytes: []byte(`"🇬🇧"`),
   750  					Range: hcl.Range{
   751  						Start: hcl.Pos{
   752  							Byte:   0,
   753  							Line:   1,
   754  							Column: 1,
   755  						},
   756  						End: hcl.Pos{
   757  							Byte:   10,
   758  							Line:   1,
   759  							Column: 4,
   760  						},
   761  					},
   762  				},
   763  				{
   764  					Type: tokenEOF,
   765  					Range: hcl.Range{
   766  						Start: hcl.Pos{
   767  							Byte:   10,
   768  							Line:   1,
   769  							Column: 4,
   770  						},
   771  						End: hcl.Pos{
   772  							Byte:   10,
   773  							Line:   1,
   774  							Column: 4,
   775  						},
   776  					},
   777  				},
   778  			},
   779  		},
   780  		{
   781  			`"á́́́́́́́"`,
   782  			[]token{
   783  				{
   784  					Type:  tokenString,
   785  					Bytes: []byte(`"á́́́́́́́"`),
   786  					Range: hcl.Range{
   787  						Start: hcl.Pos{
   788  							Byte:   0,
   789  							Line:   1,
   790  							Column: 1,
   791  						},
   792  						End: hcl.Pos{
   793  							Byte:   19,
   794  							Line:   1,
   795  							Column: 4,
   796  						},
   797  					},
   798  				},
   799  				{
   800  					Type: tokenEOF,
   801  					Range: hcl.Range{
   802  						Start: hcl.Pos{
   803  							Byte:   19,
   804  							Line:   1,
   805  							Column: 4,
   806  						},
   807  						End: hcl.Pos{
   808  							Byte:   19,
   809  							Line:   1,
   810  							Column: 4,
   811  						},
   812  					},
   813  				},
   814  			},
   815  		},
   816  		{
   817  			`&`,
   818  			[]token{
   819  				{
   820  					Type:  tokenInvalid,
   821  					Bytes: []byte(`&`),
   822  					Range: hcl.Range{
   823  						Start: hcl.Pos{
   824  							Byte:   0,
   825  							Line:   1,
   826  							Column: 1,
   827  						},
   828  						End: hcl.Pos{
   829  							Byte:   1,
   830  							Line:   1,
   831  							Column: 2,
   832  						},
   833  					},
   834  				},
   835  				{
   836  					Type: tokenEOF,
   837  					Range: hcl.Range{
   838  						Start: hcl.Pos{
   839  							Byte:   1,
   840  							Line:   1,
   841  							Column: 2,
   842  						},
   843  						End: hcl.Pos{
   844  							Byte:   1,
   845  							Line:   1,
   846  							Column: 2,
   847  						},
   848  					},
   849  				},
   850  			},
   851  		},
   852  	}
   853  
   854  	for _, test := range tests {
   855  		t.Run(test.Input, func(t *testing.T) {
   856  			buf := []byte(test.Input)
   857  			start := pos{
   858  				Filename: "",
   859  				Pos: hcl.Pos{
   860  					Byte:   0,
   861  					Line:   1,
   862  					Column: 1,
   863  				},
   864  			}
   865  			got := scan(buf, start)
   866  
   867  			if !reflect.DeepEqual(got, test.Want) {
   868  				errMsg := &bytes.Buffer{}
   869  				errMsg.WriteString("wrong result\ngot:\n")
   870  				if len(got) == 0 {
   871  					errMsg.WriteString("  (empty slice)\n")
   872  				}
   873  				for _, tok := range got {
   874  					fmt.Fprintf(errMsg, "  - %#v\n", tok)
   875  				}
   876  				errMsg.WriteString("want:\n")
   877  				if len(test.Want) == 0 {
   878  					errMsg.WriteString("  (empty slice)\n")
   879  				}
   880  				for _, tok := range test.Want {
   881  					fmt.Fprintf(errMsg, "  - %#v\n", tok)
   882  				}
   883  				t.Error(errMsg.String())
   884  			}
   885  		})
   886  	}
   887  }