get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/conf/lex_test.go (about)

     1  package conf
     2  
     3  import "testing"
     4  
     5  // Test to make sure we get what we expect.
     6  func expect(t *testing.T, lx *lexer, items []item) {
     7  	t.Helper()
     8  	for i := 0; i < len(items); i++ {
     9  		item := lx.nextItem()
    10  		_ = item.String()
    11  		if item.typ == itemEOF {
    12  			break
    13  		}
    14  		if item != items[i] {
    15  			t.Fatalf("Testing: '%s'\nExpected %q, received %q\n",
    16  				lx.input, items[i], item)
    17  		}
    18  		if item.typ == itemError {
    19  			break
    20  		}
    21  	}
    22  }
    23  
    24  func TestPlainValue(t *testing.T) {
    25  	expectedItems := []item{
    26  		{itemKey, "foo", 1, 0},
    27  		{itemEOF, "", 1, 0},
    28  	}
    29  	lx := lex("foo")
    30  	expect(t, lx, expectedItems)
    31  }
    32  
    33  func TestSimpleKeyStringValues(t *testing.T) {
    34  	// Double quotes
    35  	expectedItems := []item{
    36  		{itemKey, "foo", 1, 0},
    37  		{itemString, "bar", 1, 7},
    38  		{itemEOF, "", 1, 0},
    39  	}
    40  	lx := lex("foo = \"bar\"")
    41  	expect(t, lx, expectedItems)
    42  
    43  	// Single quotes
    44  	expectedItems = []item{
    45  		{itemKey, "foo", 1, 0},
    46  		{itemString, "bar", 1, 7},
    47  		{itemEOF, "", 1, 0},
    48  	}
    49  	lx = lex("foo = 'bar'")
    50  	expect(t, lx, expectedItems)
    51  
    52  	// No spaces
    53  	expectedItems = []item{
    54  		{itemKey, "foo", 1, 0},
    55  		{itemString, "bar", 1, 5},
    56  		{itemEOF, "", 1, 0},
    57  	}
    58  	lx = lex("foo='bar'")
    59  	expect(t, lx, expectedItems)
    60  
    61  	// NL
    62  	expectedItems = []item{
    63  		{itemKey, "foo", 1, 0},
    64  		{itemString, "bar", 1, 5},
    65  		{itemEOF, "", 1, 0},
    66  	}
    67  	lx = lex("foo='bar'\r\n")
    68  	expect(t, lx, expectedItems)
    69  
    70  	expectedItems = []item{
    71  		{itemKey, "foo", 1, 0},
    72  		{itemString, "bar", 1, 6},
    73  		{itemEOF, "", 1, 0},
    74  	}
    75  	lx = lex("foo=\t'bar'\t")
    76  	expect(t, lx, expectedItems)
    77  }
    78  
    79  func TestComplexStringValues(t *testing.T) {
    80  	expectedItems := []item{
    81  		{itemKey, "foo", 1, 0},
    82  		{itemString, "bar\\r\\n  \\t", 1, 7},
    83  		{itemEOF, "", 2, 0},
    84  	}
    85  
    86  	lx := lex("foo = 'bar\\r\\n  \\t'")
    87  	expect(t, lx, expectedItems)
    88  }
    89  
    90  func TestStringStartingWithNumber(t *testing.T) {
    91  	expectedItems := []item{
    92  		{itemKey, "foo", 1, 0},
    93  		{itemString, "3xyz", 1, 6},
    94  		{itemEOF, "", 2, 0},
    95  	}
    96  
    97  	lx := lex(`foo = 3xyz`)
    98  	expect(t, lx, expectedItems)
    99  
   100  	lx = lex(`foo = 3xyz,`)
   101  	expect(t, lx, expectedItems)
   102  
   103  	lx = lex(`foo = 3xyz;`)
   104  	expect(t, lx, expectedItems)
   105  
   106  	expectedItems = []item{
   107  		{itemKey, "foo", 2, 9},
   108  		{itemString, "3xyz", 2, 15},
   109  		{itemEOF, "", 2, 0},
   110  	}
   111  	content := `
   112          foo = 3xyz
   113          `
   114  	lx = lex(content)
   115  	expect(t, lx, expectedItems)
   116  
   117  	expectedItems = []item{
   118  		{itemKey, "map", 2, 9},
   119  		{itemMapStart, "", 2, 14},
   120  		{itemKey, "foo", 3, 11},
   121  		{itemString, "3xyz", 3, 17},
   122  		{itemMapEnd, "", 3, 22},
   123  		{itemEOF, "", 2, 0},
   124  	}
   125  	content = `
   126          map {
   127            foo = 3xyz}
   128          `
   129  	lx = lex(content)
   130  	expect(t, lx, expectedItems)
   131  
   132  	expectedItems = []item{
   133  		{itemKey, "map", 2, 9},
   134  		{itemMapStart, "", 2, 14},
   135  		{itemKey, "foo", 3, 11},
   136  		{itemString, "3xyz", 3, 17},
   137  		{itemMapEnd, "", 4, 10},
   138  		{itemEOF, "", 2, 0},
   139  	}
   140  	content = `
   141          map {
   142            foo = 3xyz;
   143          }
   144          `
   145  	lx = lex(content)
   146  	expect(t, lx, expectedItems)
   147  
   148  	expectedItems = []item{
   149  		{itemKey, "map", 2, 9},
   150  		{itemMapStart, "", 2, 14},
   151  		{itemKey, "foo", 3, 11},
   152  		{itemString, "3xyz", 3, 17},
   153  		{itemKey, "bar", 4, 11},
   154  		{itemString, "4wqs", 4, 17},
   155  		{itemMapEnd, "", 5, 10},
   156  		{itemEOF, "", 2, 0},
   157  	}
   158  	content = `
   159          map {
   160            foo = 3xyz,
   161            bar = 4wqs
   162          }
   163          `
   164  	lx = lex(content)
   165  	expect(t, lx, expectedItems)
   166  }
   167  
   168  func TestBinaryString(t *testing.T) {
   169  	expectedItems := []item{
   170  		{itemKey, "foo", 1, 0},
   171  		{itemString, "e", 1, 9},
   172  		{itemEOF, "", 1, 0},
   173  	}
   174  	lx := lex("foo = \\x65")
   175  	expect(t, lx, expectedItems)
   176  }
   177  
   178  func TestBinaryStringLatin1(t *testing.T) {
   179  	expectedItems := []item{
   180  		{itemKey, "foo", 1, 0},
   181  		{itemString, "\xe9", 1, 9},
   182  		{itemEOF, "", 1, 0},
   183  	}
   184  	lx := lex("foo = \\xe9")
   185  	expect(t, lx, expectedItems)
   186  }
   187  
   188  func TestSimpleKeyIntegerValues(t *testing.T) {
   189  	expectedItems := []item{
   190  		{itemKey, "foo", 1, 0},
   191  		{itemInteger, "123", 1, 6},
   192  		{itemEOF, "", 1, 0},
   193  	}
   194  	lx := lex("foo = 123")
   195  	expect(t, lx, expectedItems)
   196  
   197  	expectedItems = []item{
   198  		{itemKey, "foo", 1, 0},
   199  		{itemInteger, "123", 1, 4},
   200  		{itemEOF, "", 1, 0},
   201  	}
   202  	lx = lex("foo=123")
   203  	expect(t, lx, expectedItems)
   204  	lx = lex("foo=123\r\n")
   205  	expect(t, lx, expectedItems)
   206  }
   207  
   208  func TestSimpleKeyNegativeIntegerValues(t *testing.T) {
   209  	expectedItems := []item{
   210  		{itemKey, "foo", 1, 0},
   211  		{itemInteger, "-123", 1, 6},
   212  		{itemEOF, "", 1, 0},
   213  	}
   214  	lx := lex("foo = -123")
   215  	expect(t, lx, expectedItems)
   216  
   217  	expectedItems = []item{
   218  		{itemKey, "foo", 1, 0},
   219  		{itemInteger, "-123", 1, 4},
   220  		{itemEOF, "", 1, 0},
   221  	}
   222  	lx = lex("foo=-123")
   223  	expect(t, lx, expectedItems)
   224  	lx = lex("foo=-123\r\n")
   225  	expect(t, lx, expectedItems)
   226  }
   227  
   228  func TestConvenientIntegerValues(t *testing.T) {
   229  	expectedItems := []item{
   230  		{itemKey, "foo", 1, 0},
   231  		{itemInteger, "1k", 1, 6},
   232  		{itemEOF, "", 1, 0},
   233  	}
   234  	lx := lex("foo = 1k")
   235  	expect(t, lx, expectedItems)
   236  
   237  	expectedItems = []item{
   238  		{itemKey, "foo", 1, 0},
   239  		{itemInteger, "1K", 1, 6},
   240  		{itemEOF, "", 1, 0},
   241  	}
   242  	lx = lex("foo = 1K")
   243  	expect(t, lx, expectedItems)
   244  
   245  	expectedItems = []item{
   246  		{itemKey, "foo", 1, 0},
   247  		{itemInteger, "1m", 1, 6},
   248  		{itemEOF, "", 1, 0},
   249  	}
   250  	lx = lex("foo = 1m")
   251  	expect(t, lx, expectedItems)
   252  
   253  	expectedItems = []item{
   254  		{itemKey, "foo", 1, 0},
   255  		{itemInteger, "1M", 1, 6},
   256  		{itemEOF, "", 1, 0},
   257  	}
   258  	lx = lex("foo = 1M")
   259  	expect(t, lx, expectedItems)
   260  
   261  	expectedItems = []item{
   262  		{itemKey, "foo", 1, 0},
   263  		{itemInteger, "1g", 1, 6},
   264  		{itemEOF, "", 1, 0},
   265  	}
   266  	lx = lex("foo = 1g")
   267  	expect(t, lx, expectedItems)
   268  
   269  	expectedItems = []item{
   270  		{itemKey, "foo", 1, 0},
   271  		{itemInteger, "1G", 1, 6},
   272  		{itemEOF, "", 1, 0},
   273  	}
   274  	lx = lex("foo = 1G")
   275  	expect(t, lx, expectedItems)
   276  
   277  	expectedItems = []item{
   278  		{itemKey, "foo", 1, 0},
   279  		{itemInteger, "1MB", 1, 6},
   280  		{itemEOF, "", 1, 0},
   281  	}
   282  	lx = lex("foo = 1MB")
   283  	expect(t, lx, expectedItems)
   284  
   285  	expectedItems = []item{
   286  		{itemKey, "foo", 1, 0},
   287  		{itemInteger, "1Gb", 1, 6},
   288  		{itemEOF, "", 1, 0},
   289  	}
   290  	lx = lex("foo = 1Gb")
   291  	expect(t, lx, expectedItems)
   292  
   293  	// Negative versions
   294  	expectedItems = []item{
   295  		{itemKey, "foo", 1, 0},
   296  		{itemInteger, "-1m", 1, 6},
   297  		{itemEOF, "", 1, 0},
   298  	}
   299  	lx = lex("foo = -1m")
   300  	expect(t, lx, expectedItems)
   301  
   302  	expectedItems = []item{
   303  		{itemKey, "foo", 1, 0},
   304  		{itemInteger, "-1GB", 1, 6},
   305  		{itemEOF, "", 1, 0},
   306  	}
   307  	lx = lex("foo = -1GB ")
   308  	expect(t, lx, expectedItems)
   309  
   310  	expectedItems = []item{
   311  		{itemKey, "foo", 1, 0},
   312  		{itemString, "1Ghz", 1, 6},
   313  		{itemEOF, "", 1, 0},
   314  	}
   315  	lx = lex("foo = 1Ghz")
   316  	expect(t, lx, expectedItems)
   317  
   318  	expectedItems = []item{
   319  		{itemKey, "foo", 1, 0},
   320  		{itemString, "2Pie", 1, 6},
   321  		{itemEOF, "", 1, 0},
   322  	}
   323  	lx = lex("foo = 2Pie")
   324  	expect(t, lx, expectedItems)
   325  
   326  	expectedItems = []item{
   327  		{itemKey, "foo", 1, 0},
   328  		{itemString, "3Mbs", 1, 6},
   329  		{itemEOF, "", 1, 0},
   330  	}
   331  	lx = lex("foo = 3Mbs,")
   332  	expect(t, lx, expectedItems)
   333  
   334  	expectedItems = []item{
   335  		{itemKey, "foo", 1, 0},
   336  		{itemInteger, "4Gb", 1, 6},
   337  		{itemKey, "bar", 1, 11},
   338  		{itemString, "5Gø", 1, 17},
   339  		{itemEOF, "", 1, 0},
   340  	}
   341  	lx = lex("foo = 4Gb, bar = 5Gø")
   342  	expect(t, lx, expectedItems)
   343  }
   344  
   345  func TestSimpleKeyFloatValues(t *testing.T) {
   346  	expectedItems := []item{
   347  		{itemKey, "foo", 1, 0},
   348  		{itemFloat, "22.2", 1, 6},
   349  		{itemEOF, "", 1, 0},
   350  	}
   351  	lx := lex("foo = 22.2")
   352  	expect(t, lx, expectedItems)
   353  
   354  	expectedItems = []item{
   355  		{itemKey, "foo", 1, 0},
   356  		{itemFloat, "22.2", 1, 4},
   357  		{itemEOF, "", 1, 0},
   358  	}
   359  	lx = lex("foo=22.2")
   360  	expect(t, lx, expectedItems)
   361  	lx = lex("foo=22.2\r\n")
   362  	expect(t, lx, expectedItems)
   363  }
   364  
   365  func TestBadBinaryStringEndingAfterZeroHexChars(t *testing.T) {
   366  	expectedItems := []item{
   367  		{itemKey, "foo", 1, 0},
   368  		{itemError, "Expected two hexadecimal digits after '\\x', but hit end of line", 2, 1},
   369  		{itemEOF, "", 1, 0},
   370  	}
   371  	lx := lex("foo = xyz\\x\n")
   372  	expect(t, lx, expectedItems)
   373  }
   374  
   375  func TestBadBinaryStringEndingAfterOneHexChar(t *testing.T) {
   376  	expectedItems := []item{
   377  		{itemKey, "foo", 1, 0},
   378  		{itemError, "Expected two hexadecimal digits after '\\x', but hit end of line", 2, 1},
   379  		{itemEOF, "", 1, 0},
   380  	}
   381  	lx := lex("foo = xyz\\xF\n")
   382  	expect(t, lx, expectedItems)
   383  }
   384  
   385  func TestBadBinaryStringWithZeroHexChars(t *testing.T) {
   386  	expectedItems := []item{
   387  		{itemKey, "foo", 1, 0},
   388  		{itemError, "Expected two hexadecimal digits after '\\x', but got ']\"'", 1, 12},
   389  		{itemEOF, "", 1, 0},
   390  	}
   391  	lx := lex(`foo = "[\x]"`)
   392  	expect(t, lx, expectedItems)
   393  }
   394  
   395  func TestBadBinaryStringWithOneHexChar(t *testing.T) {
   396  	expectedItems := []item{
   397  		{itemKey, "foo", 1, 0},
   398  		{itemError, "Expected two hexadecimal digits after '\\x', but got 'e]'", 1, 12},
   399  		{itemEOF, "", 1, 0},
   400  	}
   401  	lx := lex(`foo = "[\xe]"`)
   402  	expect(t, lx, expectedItems)
   403  }
   404  
   405  func TestBadFloatValues(t *testing.T) {
   406  	expectedItems := []item{
   407  		{itemKey, "foo", 1, 0},
   408  		{itemError, "Floats must start with a digit", 1, 7},
   409  		{itemEOF, "", 1, 0},
   410  	}
   411  	lx := lex("foo = .2")
   412  	expect(t, lx, expectedItems)
   413  }
   414  
   415  func TestBadKey(t *testing.T) {
   416  	expectedItems := []item{
   417  		{itemError, "Unexpected key separator ':'", 1, 1},
   418  		{itemEOF, "", 1, 0},
   419  	}
   420  	lx := lex(" :foo = 22")
   421  	expect(t, lx, expectedItems)
   422  }
   423  
   424  func TestSimpleKeyBoolValues(t *testing.T) {
   425  	expectedItems := []item{
   426  		{itemKey, "foo", 1, 0},
   427  		{itemBool, "true", 1, 6},
   428  		{itemEOF, "", 1, 0},
   429  	}
   430  	lx := lex("foo = true")
   431  	expect(t, lx, expectedItems)
   432  
   433  	expectedItems = []item{
   434  		{itemKey, "foo", 1, 0},
   435  		{itemBool, "true", 1, 4},
   436  		{itemEOF, "", 1, 0},
   437  	}
   438  	lx = lex("foo=true")
   439  	expect(t, lx, expectedItems)
   440  	lx = lex("foo=true\r\n")
   441  	expect(t, lx, expectedItems)
   442  }
   443  
   444  func TestComments(t *testing.T) {
   445  	expectedItems := []item{
   446  		{itemCommentStart, "", 1, 1},
   447  		{itemText, " This is a comment", 1, 1},
   448  		{itemEOF, "", 1, 0},
   449  	}
   450  	lx := lex("# This is a comment")
   451  	expect(t, lx, expectedItems)
   452  	lx = lex("# This is a comment\r\n")
   453  	expect(t, lx, expectedItems)
   454  
   455  	expectedItems = []item{
   456  		{itemCommentStart, "", 1, 2},
   457  		{itemText, " This is a comment", 1, 2},
   458  		{itemEOF, "", 1, 0},
   459  	}
   460  	lx = lex("// This is a comment\r\n")
   461  	expect(t, lx, expectedItems)
   462  }
   463  
   464  func TestTopValuesWithComments(t *testing.T) {
   465  	expectedItems := []item{
   466  		{itemKey, "foo", 1, 0},
   467  		{itemInteger, "123", 1, 6},
   468  		{itemCommentStart, "", 1, 12},
   469  		{itemText, " This is a comment", 1, 12},
   470  		{itemEOF, "", 1, 0},
   471  	}
   472  
   473  	lx := lex("foo = 123 // This is a comment")
   474  	expect(t, lx, expectedItems)
   475  
   476  	expectedItems = []item{
   477  		{itemKey, "foo", 1, 0},
   478  		{itemInteger, "123", 1, 4},
   479  		{itemCommentStart, "", 1, 12},
   480  		{itemText, " This is a comment", 1, 12},
   481  		{itemEOF, "", 1, 0},
   482  	}
   483  	lx = lex("foo=123    # This is a comment")
   484  	expect(t, lx, expectedItems)
   485  }
   486  
   487  func TestRawString(t *testing.T) {
   488  	expectedItems := []item{
   489  		{itemKey, "foo", 1, 0},
   490  		{itemString, "bar", 1, 6},
   491  		{itemEOF, "", 1, 0},
   492  	}
   493  	lx := lex("foo = bar")
   494  	expect(t, lx, expectedItems)
   495  	lx = lex(`foo = bar' `)
   496  	expect(t, lx, expectedItems)
   497  }
   498  
   499  func TestDateValues(t *testing.T) {
   500  	expectedItems := []item{
   501  		{itemKey, "foo", 1, 0},
   502  		{itemDatetime, "2016-05-04T18:53:41Z", 1, 6},
   503  		{itemEOF, "", 1, 0},
   504  	}
   505  
   506  	lx := lex("foo = 2016-05-04T18:53:41Z")
   507  	expect(t, lx, expectedItems)
   508  }
   509  
   510  func TestVariableValues(t *testing.T) {
   511  	expectedItems := []item{
   512  		{itemKey, "foo", 1, 0},
   513  		{itemVariable, "bar", 1, 7},
   514  		{itemEOF, "", 1, 0},
   515  	}
   516  	lx := lex("foo = $bar")
   517  	expect(t, lx, expectedItems)
   518  
   519  	expectedItems = []item{
   520  		{itemKey, "foo", 1, 0},
   521  		{itemVariable, "bar", 1, 6},
   522  		{itemEOF, "", 1, 0},
   523  	}
   524  	lx = lex("foo =$bar")
   525  	expect(t, lx, expectedItems)
   526  
   527  	expectedItems = []item{
   528  		{itemKey, "foo", 1, 0},
   529  		{itemVariable, "bar", 1, 5},
   530  		{itemEOF, "", 1, 0},
   531  	}
   532  	lx = lex("foo $bar")
   533  	expect(t, lx, expectedItems)
   534  }
   535  
   536  func TestArrays(t *testing.T) {
   537  	expectedItems := []item{
   538  		{itemKey, "foo", 1, 0},
   539  		{itemArrayStart, "", 1, 7},
   540  		{itemInteger, "1", 1, 7},
   541  		{itemInteger, "2", 1, 10},
   542  		{itemInteger, "3", 1, 13},
   543  		{itemString, "bar", 1, 17},
   544  		{itemArrayEnd, "", 1, 22},
   545  		{itemEOF, "", 1, 0},
   546  	}
   547  	lx := lex("foo = [1, 2, 3, 'bar']")
   548  	expect(t, lx, expectedItems)
   549  
   550  	expectedItems = []item{
   551  		{itemKey, "foo", 1, 0},
   552  		{itemArrayStart, "", 1, 7},
   553  		{itemInteger, "1", 1, 7},
   554  		{itemInteger, "2", 1, 9},
   555  		{itemInteger, "3", 1, 11},
   556  		{itemString, "bar", 1, 14},
   557  		{itemArrayEnd, "", 1, 19},
   558  		{itemEOF, "", 1, 0},
   559  	}
   560  	lx = lex("foo = [1,2,3,'bar']")
   561  	expect(t, lx, expectedItems)
   562  
   563  	expectedItems = []item{
   564  		{itemKey, "foo", 1, 0},
   565  		{itemArrayStart, "", 1, 7},
   566  		{itemInteger, "1", 1, 7},
   567  		{itemInteger, "2", 1, 10},
   568  		{itemInteger, "3", 1, 12},
   569  		{itemString, "bar", 1, 15},
   570  		{itemArrayEnd, "", 1, 20},
   571  		{itemEOF, "", 1, 0},
   572  	}
   573  	lx = lex("foo = [1, 2,3,'bar']")
   574  	expect(t, lx, expectedItems)
   575  }
   576  
   577  var mlArray = `
   578  # top level comment
   579  foo = [
   580   1, # One
   581   2, // Two
   582   3 # Three
   583   'bar'     ,
   584   "bar"
   585  ]
   586  `
   587  
   588  func TestMultilineArrays(t *testing.T) {
   589  	expectedItems := []item{
   590  		{itemCommentStart, "", 2, 2},
   591  		{itemText, " top level comment", 2, 2},
   592  		{itemKey, "foo", 3, 1},
   593  		{itemArrayStart, "", 3, 8},
   594  		{itemInteger, "1", 4, 2},
   595  		{itemCommentStart, "", 4, 6},
   596  		{itemText, " One", 4, 6},
   597  		{itemInteger, "2", 5, 2},
   598  		{itemCommentStart, "", 5, 7},
   599  		{itemText, " Two", 5, 7},
   600  		{itemInteger, "3", 6, 2},
   601  		{itemCommentStart, "", 6, 5},
   602  		{itemText, " Three", 6, 5},
   603  		{itemString, "bar", 7, 3},
   604  		{itemString, "bar", 8, 3},
   605  		{itemArrayEnd, "", 9, 2},
   606  		{itemEOF, "", 9, 0},
   607  	}
   608  	lx := lex(mlArray)
   609  	expect(t, lx, expectedItems)
   610  }
   611  
   612  var mlArrayNoSep = `
   613  # top level comment
   614  foo = [
   615   1 // foo
   616   2
   617   3
   618   'bar'
   619   "bar"
   620  ]
   621  `
   622  
   623  func TestMultilineArraysNoSep(t *testing.T) {
   624  	expectedItems := []item{
   625  		{itemCommentStart, "", 2, 2},
   626  		{itemText, " top level comment", 2, 2},
   627  		{itemKey, "foo", 3, 1},
   628  		{itemArrayStart, "", 3, 8},
   629  		{itemInteger, "1", 4, 2},
   630  		{itemCommentStart, "", 4, 6},
   631  		{itemText, " foo", 4, 6},
   632  		{itemInteger, "2", 5, 2},
   633  		{itemInteger, "3", 6, 2},
   634  		{itemString, "bar", 7, 3},
   635  		{itemString, "bar", 8, 3},
   636  		{itemArrayEnd, "", 9, 2},
   637  		{itemEOF, "", 9, 0},
   638  	}
   639  	lx := lex(mlArrayNoSep)
   640  	expect(t, lx, expectedItems)
   641  }
   642  
   643  func TestSimpleMap(t *testing.T) {
   644  	expectedItems := []item{
   645  		{itemKey, "foo", 1, 0},
   646  		{itemMapStart, "", 1, 7},
   647  		{itemKey, "ip", 1, 7},
   648  		{itemString, "127.0.0.1", 1, 11},
   649  		{itemKey, "port", 1, 23},
   650  		{itemInteger, "4242", 1, 30},
   651  		{itemMapEnd, "", 1, 35},
   652  		{itemEOF, "", 1, 0},
   653  	}
   654  
   655  	lx := lex("foo = {ip='127.0.0.1', port = 4242}")
   656  	expect(t, lx, expectedItems)
   657  }
   658  
   659  var mlMap = `
   660  foo = {
   661    ip = '127.0.0.1' # the IP
   662    port= 4242 // the port
   663  }
   664  `
   665  
   666  func TestMultilineMap(t *testing.T) {
   667  	expectedItems := []item{
   668  		{itemKey, "foo", 2, 1},
   669  		{itemMapStart, "", 2, 8},
   670  		{itemKey, "ip", 3, 3},
   671  		{itemString, "127.0.0.1", 3, 9},
   672  		{itemCommentStart, "", 3, 21},
   673  		{itemText, " the IP", 3, 21},
   674  		{itemKey, "port", 4, 3},
   675  		{itemInteger, "4242", 4, 9},
   676  		{itemCommentStart, "", 4, 16},
   677  		{itemText, " the port", 4, 16},
   678  		{itemMapEnd, "", 5, 2},
   679  		{itemEOF, "", 5, 0},
   680  	}
   681  
   682  	lx := lex(mlMap)
   683  	expect(t, lx, expectedItems)
   684  }
   685  
   686  var nestedMap = `
   687  foo = {
   688    host = {
   689      ip = '127.0.0.1'
   690      port= 4242
   691    }
   692  }
   693  `
   694  
   695  func TestNestedMaps(t *testing.T) {
   696  	expectedItems := []item{
   697  		{itemKey, "foo", 2, 1},
   698  		{itemMapStart, "", 2, 8},
   699  		{itemKey, "host", 3, 3},
   700  		{itemMapStart, "", 3, 11},
   701  		{itemKey, "ip", 4, 5},
   702  		{itemString, "127.0.0.1", 4, 11},
   703  		{itemKey, "port", 5, 5},
   704  		{itemInteger, "4242", 5, 11},
   705  		{itemMapEnd, "", 6, 4},
   706  		{itemMapEnd, "", 7, 2},
   707  		{itemEOF, "", 7, 0},
   708  	}
   709  
   710  	lx := lex(nestedMap)
   711  	expect(t, lx, expectedItems)
   712  }
   713  
   714  func TestQuotedKeys(t *testing.T) {
   715  	expectedItems := []item{
   716  		{itemKey, "foo", 1, 0},
   717  		{itemInteger, "123", 1, 6},
   718  		{itemEOF, "", 1, 0},
   719  	}
   720  	lx := lex("foo : 123")
   721  	expect(t, lx, expectedItems)
   722  
   723  	expectedItems = []item{
   724  		{itemKey, "foo", 1, 1},
   725  		{itemInteger, "123", 1, 8},
   726  		{itemEOF, "", 1, 0},
   727  	}
   728  	lx = lex("'foo' : 123")
   729  	expect(t, lx, expectedItems)
   730  	lx = lex("\"foo\" : 123")
   731  	expect(t, lx, expectedItems)
   732  }
   733  
   734  func TestQuotedKeysWithSpace(t *testing.T) {
   735  	expectedItems := []item{
   736  		{itemKey, " foo", 1, 1},
   737  		{itemInteger, "123", 1, 9},
   738  		{itemEOF, "", 1, 0},
   739  	}
   740  	lx := lex("' foo' : 123")
   741  	expect(t, lx, expectedItems)
   742  
   743  	expectedItems = []item{
   744  		{itemKey, " foo", 1, 1},
   745  		{itemInteger, "123", 1, 9},
   746  		{itemEOF, "", 1, 0},
   747  	}
   748  	lx = lex("\" foo\" : 123")
   749  	expect(t, lx, expectedItems)
   750  }
   751  
   752  func TestColonKeySep(t *testing.T) {
   753  	expectedItems := []item{
   754  		{itemKey, "foo", 1, 0},
   755  		{itemInteger, "123", 1, 6},
   756  		{itemEOF, "", 1, 0},
   757  	}
   758  	lx := lex("foo : 123")
   759  	expect(t, lx, expectedItems)
   760  
   761  	expectedItems = []item{
   762  		{itemKey, "foo", 1, 0},
   763  		{itemInteger, "123", 1, 4},
   764  		{itemEOF, "", 1, 0},
   765  	}
   766  	lx = lex("foo:123")
   767  	expect(t, lx, expectedItems)
   768  
   769  	expectedItems = []item{
   770  		{itemKey, "foo", 1, 0},
   771  		{itemInteger, "123", 1, 5},
   772  		{itemEOF, "", 1, 0},
   773  	}
   774  	lx = lex("foo: 123")
   775  	expect(t, lx, expectedItems)
   776  
   777  	expectedItems = []item{
   778  		{itemKey, "foo", 1, 0},
   779  		{itemInteger, "123", 1, 6},
   780  		{itemEOF, "", 1, 0},
   781  	}
   782  	lx = lex("foo:  123\r\n")
   783  	expect(t, lx, expectedItems)
   784  }
   785  
   786  func TestWhitespaceKeySep(t *testing.T) {
   787  	expectedItems := []item{
   788  		{itemKey, "foo", 1, 0},
   789  		{itemInteger, "123", 1, 4},
   790  		{itemEOF, "", 1, 0},
   791  	}
   792  	lx := lex("foo 123")
   793  	expect(t, lx, expectedItems)
   794  	lx = lex("foo 123")
   795  	expect(t, lx, expectedItems)
   796  	lx = lex("foo\t123")
   797  	expect(t, lx, expectedItems)
   798  	expectedItems = []item{
   799  		{itemKey, "foo", 1, 0},
   800  		{itemInteger, "123", 1, 5},
   801  		{itemEOF, "", 1, 0},
   802  	}
   803  	lx = lex("foo\t\t123\r\n")
   804  	expect(t, lx, expectedItems)
   805  }
   806  
   807  var escString = `
   808  foo  = \t
   809  bar  = \r
   810  baz  = \n
   811  q    = \"
   812  bs   = \\
   813  `
   814  
   815  func TestEscapedString(t *testing.T) {
   816  	expectedItems := []item{
   817  		{itemKey, "foo", 2, 1},
   818  		{itemString, "\t", 2, 9},
   819  		{itemKey, "bar", 3, 1},
   820  		{itemString, "\r", 3, 9},
   821  		{itemKey, "baz", 4, 1},
   822  		{itemString, "\n", 4, 9},
   823  		{itemKey, "q", 5, 1},
   824  		{itemString, "\"", 5, 9},
   825  		{itemKey, "bs", 6, 1},
   826  		{itemString, "\\", 6, 9},
   827  		{itemEOF, "", 6, 0},
   828  	}
   829  	lx := lex(escString)
   830  	expect(t, lx, expectedItems)
   831  }
   832  
   833  func TestCompoundStringES(t *testing.T) {
   834  	expectedItems := []item{
   835  		{itemKey, "foo", 1, 0},
   836  		{itemString, "\\end", 1, 8},
   837  		{itemEOF, "", 2, 0},
   838  	}
   839  	lx := lex(`foo = "\\end"`)
   840  	expect(t, lx, expectedItems)
   841  }
   842  
   843  func TestCompoundStringSE(t *testing.T) {
   844  	expectedItems := []item{
   845  		{itemKey, "foo", 1, 0},
   846  		{itemString, "start\\", 1, 8},
   847  		{itemEOF, "", 2, 0},
   848  	}
   849  	lx := lex(`foo = "start\\"`)
   850  	expect(t, lx, expectedItems)
   851  }
   852  
   853  func TestCompoundStringEE(t *testing.T) {
   854  	expectedItems := []item{
   855  		{itemKey, "foo", 1, 0},
   856  		{itemString, "Eq", 1, 12},
   857  		{itemEOF, "", 2, 0},
   858  	}
   859  	lx := lex(`foo = \x45\x71`)
   860  	expect(t, lx, expectedItems)
   861  }
   862  
   863  func TestCompoundStringSEE(t *testing.T) {
   864  	expectedItems := []item{
   865  		{itemKey, "foo", 1, 0},
   866  		{itemString, "startEq", 1, 12},
   867  		{itemEOF, "", 2, 0},
   868  	}
   869  	lx := lex(`foo = start\x45\x71`)
   870  	expect(t, lx, expectedItems)
   871  }
   872  
   873  func TestCompoundStringSES(t *testing.T) {
   874  	expectedItems := []item{
   875  		{itemKey, "foo", 1, 0},
   876  		{itemString, "start|end", 1, 9},
   877  		{itemEOF, "", 2, 0},
   878  	}
   879  	lx := lex(`foo = start\x7Cend`)
   880  	expect(t, lx, expectedItems)
   881  }
   882  
   883  func TestCompoundStringEES(t *testing.T) {
   884  	expectedItems := []item{
   885  		{itemKey, "foo", 1, 0},
   886  		{itemString, "<>end", 1, 12},
   887  		{itemEOF, "", 2, 0},
   888  	}
   889  	lx := lex(`foo = \x3c\x3eend`)
   890  	expect(t, lx, expectedItems)
   891  }
   892  
   893  func TestCompoundStringESE(t *testing.T) {
   894  	expectedItems := []item{
   895  		{itemKey, "foo", 1, 0},
   896  		{itemString, "<middle>", 1, 12},
   897  		{itemEOF, "", 2, 0},
   898  	}
   899  	lx := lex(`foo = \x3cmiddle\x3E`)
   900  	expect(t, lx, expectedItems)
   901  }
   902  
   903  func TestBadStringEscape(t *testing.T) {
   904  	expectedItems := []item{
   905  		{itemKey, "foo", 1, 0},
   906  		{itemError, "Invalid escape character 'y'. Only the following escape characters are allowed: \\xXX, \\t, \\n, \\r, \\\", \\\\.", 1, 8},
   907  		{itemEOF, "", 2, 0},
   908  	}
   909  	lx := lex(`foo = \y`)
   910  	expect(t, lx, expectedItems)
   911  }
   912  
   913  func TestNonBool(t *testing.T) {
   914  	expectedItems := []item{
   915  		{itemKey, "foo", 1, 0},
   916  		{itemString, "\\true", 1, 7},
   917  		{itemEOF, "", 2, 0},
   918  	}
   919  	lx := lex(`foo = \\true`)
   920  	expect(t, lx, expectedItems)
   921  }
   922  
   923  func TestNonVariable(t *testing.T) {
   924  	expectedItems := []item{
   925  		{itemKey, "foo", 1, 0},
   926  		{itemString, "\\$var", 1, 7},
   927  		{itemEOF, "", 2, 0},
   928  	}
   929  	lx := lex(`foo = \\$var`)
   930  	expect(t, lx, expectedItems)
   931  }
   932  
   933  func TestEmptyStringDQ(t *testing.T) {
   934  	expectedItems := []item{
   935  		{itemKey, "foo", 1, 0},
   936  		{itemString, "", 1, 7},
   937  		{itemEOF, "", 2, 0},
   938  	}
   939  	lx := lex(`foo = ""`)
   940  	expect(t, lx, expectedItems)
   941  }
   942  
   943  func TestEmptyStringSQ(t *testing.T) {
   944  	expectedItems := []item{
   945  		{itemKey, "foo", 1, 0},
   946  		{itemString, "", 1, 7},
   947  		{itemEOF, "", 2, 0},
   948  	}
   949  	lx := lex(`foo = ''`)
   950  	expect(t, lx, expectedItems)
   951  }
   952  
   953  var nestedWhitespaceMap = `
   954  foo  {
   955    host  {
   956      ip = '127.0.0.1'
   957      port= 4242
   958    }
   959  }
   960  `
   961  
   962  func TestNestedWhitespaceMaps(t *testing.T) {
   963  	expectedItems := []item{
   964  		{itemKey, "foo", 2, 1},
   965  		{itemMapStart, "", 2, 7},
   966  		{itemKey, "host", 3, 3},
   967  		{itemMapStart, "", 3, 10},
   968  		{itemKey, "ip", 4, 5},
   969  		{itemString, "127.0.0.1", 4, 11},
   970  		{itemKey, "port", 5, 5},
   971  		{itemInteger, "4242", 5, 11},
   972  		{itemMapEnd, "", 6, 4},
   973  		{itemMapEnd, "", 7, 2},
   974  		{itemEOF, "", 7, 0},
   975  	}
   976  
   977  	lx := lex(nestedWhitespaceMap)
   978  	expect(t, lx, expectedItems)
   979  }
   980  
   981  var semicolons = `
   982  foo = 123;
   983  bar = 'baz';
   984  baz = 'boo'
   985  map {
   986   id = 1;
   987  }
   988  `
   989  
   990  func TestOptionalSemicolons(t *testing.T) {
   991  	expectedItems := []item{
   992  		{itemKey, "foo", 2, 1},
   993  		{itemInteger, "123", 2, 7},
   994  		{itemKey, "bar", 3, 1},
   995  		{itemString, "baz", 3, 8},
   996  		{itemKey, "baz", 4, 1},
   997  		{itemString, "boo", 4, 8},
   998  		{itemKey, "map", 5, 1},
   999  		{itemMapStart, "", 5, 6},
  1000  		{itemKey, "id", 6, 2},
  1001  		{itemInteger, "1", 6, 7},
  1002  		{itemMapEnd, "", 7, 2},
  1003  		{itemEOF, "", 8, 0},
  1004  	}
  1005  
  1006  	lx := lex(semicolons)
  1007  	expect(t, lx, expectedItems)
  1008  }
  1009  
  1010  func TestSemicolonChaining(t *testing.T) {
  1011  	expectedItems := []item{
  1012  		{itemKey, "foo", 1, 0},
  1013  		{itemString, "1", 1, 5},
  1014  		{itemKey, "bar", 1, 9},
  1015  		{itemFloat, "2.2", 1, 13},
  1016  		{itemKey, "baz", 1, 18},
  1017  		{itemBool, "true", 1, 22},
  1018  		{itemEOF, "", 1, 0},
  1019  	}
  1020  
  1021  	lx := lex("foo='1'; bar=2.2; baz=true;")
  1022  	expect(t, lx, expectedItems)
  1023  }
  1024  
  1025  var noquotes = `
  1026  foo = 123
  1027  bar = baz
  1028  baz=boo
  1029  map {
  1030   id:one
  1031   id2 : onetwo
  1032  }
  1033  t true
  1034  f false
  1035  tstr "true"
  1036  tkey = two
  1037  fkey = five # This should be a string
  1038  `
  1039  
  1040  func TestNonQuotedStrings(t *testing.T) {
  1041  	expectedItems := []item{
  1042  		{itemKey, "foo", 2, 1},
  1043  		{itemInteger, "123", 2, 7},
  1044  		{itemKey, "bar", 3, 1},
  1045  		{itemString, "baz", 3, 7},
  1046  		{itemKey, "baz", 4, 1},
  1047  		{itemString, "boo", 4, 5},
  1048  		{itemKey, "map", 5, 1},
  1049  		{itemMapStart, "", 5, 6},
  1050  		{itemKey, "id", 6, 2},
  1051  		{itemString, "one", 6, 5},
  1052  		{itemKey, "id2", 7, 2},
  1053  		{itemString, "onetwo", 7, 8},
  1054  		{itemMapEnd, "", 8, 2},
  1055  		{itemKey, "t", 9, 1},
  1056  		{itemBool, "true", 9, 3},
  1057  		{itemKey, "f", 10, 1},
  1058  		{itemBool, "false", 10, 3},
  1059  		{itemKey, "tstr", 11, 1},
  1060  		{itemString, "true", 11, 7},
  1061  		{itemKey, "tkey", 12, 1},
  1062  		{itemString, "two", 12, 8},
  1063  		{itemKey, "fkey", 13, 1},
  1064  		{itemString, "five", 13, 8},
  1065  		{itemCommentStart, "", 13, 14},
  1066  		{itemText, " This should be a string", 13, 14},
  1067  		{itemEOF, "", 14, 0},
  1068  	}
  1069  	lx := lex(noquotes)
  1070  	expect(t, lx, expectedItems)
  1071  }
  1072  
  1073  var danglingquote = `
  1074  listen: "localhost:4242
  1075  
  1076  http: localhost:8222
  1077  `
  1078  
  1079  func TestDanglingQuotedString(t *testing.T) {
  1080  	expectedItems := []item{
  1081  		{itemKey, "listen", 2, 1},
  1082  		{itemError, "Unexpected EOF.", 5, 1},
  1083  	}
  1084  	lx := lex(danglingquote)
  1085  	expect(t, lx, expectedItems)
  1086  }
  1087  
  1088  var keydanglingquote = `
  1089  foo = "
  1090  listen: "
  1091  
  1092  http: localhost:8222
  1093  
  1094  "
  1095  `
  1096  
  1097  func TestKeyDanglingQuotedString(t *testing.T) {
  1098  	expectedItems := []item{
  1099  		{itemKey, "foo", 2, 1},
  1100  		{itemString, "\nlisten: ", 3, 8},
  1101  		{itemKey, "http", 5, 1},
  1102  		{itemString, "localhost:8222", 5, 7},
  1103  		{itemError, "Unexpected EOF.", 8, 1},
  1104  	}
  1105  	lx := lex(keydanglingquote)
  1106  	expect(t, lx, expectedItems)
  1107  }
  1108  
  1109  var danglingsquote = `
  1110  listen: 'localhost:4242
  1111  
  1112  http: localhost:8222
  1113  `
  1114  
  1115  func TestDanglingSingleQuotedString(t *testing.T) {
  1116  	expectedItems := []item{
  1117  		{itemKey, "listen", 2, 1},
  1118  		{itemError, "Unexpected EOF.", 5, 1},
  1119  	}
  1120  	lx := lex(danglingsquote)
  1121  	expect(t, lx, expectedItems)
  1122  }
  1123  
  1124  var keydanglingsquote = `
  1125  foo = '
  1126  listen: '
  1127  
  1128  http: localhost:8222
  1129  
  1130  '
  1131  `
  1132  
  1133  func TestKeyDanglingSingleQuotedString(t *testing.T) {
  1134  	expectedItems := []item{
  1135  		{itemKey, "foo", 2, 1},
  1136  		{itemString, "\nlisten: ", 3, 8},
  1137  		{itemKey, "http", 5, 1},
  1138  		{itemString, "localhost:8222", 5, 7},
  1139  		{itemError, "Unexpected EOF.", 8, 1},
  1140  	}
  1141  	lx := lex(keydanglingsquote)
  1142  	expect(t, lx, expectedItems)
  1143  }
  1144  
  1145  var mapdanglingbracket = `
  1146  listen = 4222
  1147  
  1148  cluster = {
  1149  
  1150    foo = bar
  1151  
  1152  `
  1153  
  1154  func TestMapDanglingBracket(t *testing.T) {
  1155  	expectedItems := []item{
  1156  		{itemKey, "listen", 2, 1},
  1157  		{itemInteger, "4222", 2, 10},
  1158  		{itemKey, "cluster", 4, 1},
  1159  		{itemMapStart, "", 4, 12},
  1160  		{itemKey, "foo", 6, 3},
  1161  		{itemString, "bar", 6, 9},
  1162  		{itemError, "Unexpected EOF processing map.", 8, 1},
  1163  	}
  1164  	lx := lex(mapdanglingbracket)
  1165  	expect(t, lx, expectedItems)
  1166  }
  1167  
  1168  var blockdanglingparens = `
  1169  listen = 4222
  1170  
  1171  quote = (
  1172  
  1173    foo = bar
  1174  
  1175  `
  1176  
  1177  func TestBlockDanglingParens(t *testing.T) {
  1178  	expectedItems := []item{
  1179  		{itemKey, "listen", 2, 1},
  1180  		{itemInteger, "4222", 2, 10},
  1181  		{itemKey, "quote", 4, 1},
  1182  		{itemError, "Unexpected EOF processing block.", 8, 1},
  1183  	}
  1184  	lx := lex(blockdanglingparens)
  1185  	expect(t, lx, expectedItems)
  1186  }
  1187  
  1188  func TestMapQuotedKeys(t *testing.T) {
  1189  	expectedItems := []item{
  1190  		{itemKey, "foo", 1, 0},
  1191  		{itemMapStart, "", 1, 7},
  1192  		{itemKey, "bar", 1, 8},
  1193  		{itemInteger, "4242", 1, 15},
  1194  		{itemMapEnd, "", 1, 20},
  1195  		{itemEOF, "", 1, 0},
  1196  	}
  1197  	lx := lex("foo = {'bar' = 4242}")
  1198  	expect(t, lx, expectedItems)
  1199  	lx = lex("foo = {\"bar\" = 4242}")
  1200  	expect(t, lx, expectedItems)
  1201  }
  1202  
  1203  func TestSpecialCharsMapQuotedKeys(t *testing.T) {
  1204  	expectedItems := []item{
  1205  		{itemKey, "foo", 1, 0},
  1206  		{itemMapStart, "", 1, 7},
  1207  		{itemKey, "bar-1.2.3", 1, 8},
  1208  		{itemMapStart, "", 1, 22},
  1209  		{itemKey, "port", 1, 23},
  1210  		{itemInteger, "4242", 1, 28},
  1211  		{itemMapEnd, "", 1, 34},
  1212  		{itemMapEnd, "", 1, 35},
  1213  		{itemEOF, "", 1, 0},
  1214  	}
  1215  	lx := lex("foo = {'bar-1.2.3' = { port:4242 }}")
  1216  	expect(t, lx, expectedItems)
  1217  	lx = lex("foo = {\"bar-1.2.3\" = { port:4242 }}")
  1218  	expect(t, lx, expectedItems)
  1219  }
  1220  
  1221  var mlnestedmap = `
  1222  systems {
  1223    allinone {
  1224      description: "This is a description."
  1225    }
  1226  }
  1227  `
  1228  
  1229  func TestDoubleNestedMapsNewLines(t *testing.T) {
  1230  	expectedItems := []item{
  1231  		{itemKey, "systems", 2, 1},
  1232  		{itemMapStart, "", 2, 10},
  1233  		{itemKey, "allinone", 3, 3},
  1234  		{itemMapStart, "", 3, 13},
  1235  		{itemKey, "description", 4, 5},
  1236  		{itemString, "This is a description.", 4, 19},
  1237  		{itemMapEnd, "", 5, 4},
  1238  		{itemMapEnd, "", 6, 2},
  1239  		{itemEOF, "", 7, 0},
  1240  	}
  1241  	lx := lex(mlnestedmap)
  1242  	expect(t, lx, expectedItems)
  1243  }
  1244  
  1245  var blockexample = `
  1246  numbers (
  1247  1234567890
  1248  )
  1249  `
  1250  
  1251  func TestBlockString(t *testing.T) {
  1252  	expectedItems := []item{
  1253  		{itemKey, "numbers", 2, 1},
  1254  		{itemString, "\n1234567890\n", 4, 10},
  1255  	}
  1256  	lx := lex(blockexample)
  1257  	expect(t, lx, expectedItems)
  1258  }
  1259  
  1260  func TestBlockStringEOF(t *testing.T) {
  1261  	expectedItems := []item{
  1262  		{itemKey, "numbers", 2, 1},
  1263  		{itemString, "\n1234567890\n", 4, 10},
  1264  	}
  1265  	blockbytes := []byte(blockexample[0 : len(blockexample)-1])
  1266  	blockbytes = append(blockbytes, 0)
  1267  	lx := lex(string(blockbytes))
  1268  	expect(t, lx, expectedItems)
  1269  }
  1270  
  1271  var mlblockexample = `
  1272  numbers (
  1273    12(34)56
  1274    (
  1275      7890
  1276    )
  1277  )
  1278  `
  1279  
  1280  func TestBlockStringMultiLine(t *testing.T) {
  1281  	expectedItems := []item{
  1282  		{itemKey, "numbers", 2, 1},
  1283  		{itemString, "\n  12(34)56\n  (\n    7890\n  )\n", 7, 10},
  1284  	}
  1285  	lx := lex(mlblockexample)
  1286  	expect(t, lx, expectedItems)
  1287  }
  1288  
  1289  func TestUnquotedIPAddr(t *testing.T) {
  1290  	expectedItems := []item{
  1291  		{itemKey, "listen", 1, 0},
  1292  		{itemString, "127.0.0.1:4222", 1, 8},
  1293  		{itemEOF, "", 1, 0},
  1294  	}
  1295  	lx := lex("listen: 127.0.0.1:4222")
  1296  	expect(t, lx, expectedItems)
  1297  
  1298  	expectedItems = []item{
  1299  		{itemKey, "listen", 1, 0},
  1300  		{itemString, "127.0.0.1", 1, 8},
  1301  		{itemEOF, "", 1, 0},
  1302  	}
  1303  	lx = lex("listen: 127.0.0.1")
  1304  	expect(t, lx, expectedItems)
  1305  
  1306  	expectedItems = []item{
  1307  		{itemKey, "listen", 1, 0},
  1308  		{itemString, "apcera.me:80", 1, 8},
  1309  		{itemEOF, "", 1, 0},
  1310  	}
  1311  	lx = lex("listen: apcera.me:80")
  1312  	expect(t, lx, expectedItems)
  1313  
  1314  	expectedItems = []item{
  1315  		{itemKey, "listen", 1, 0},
  1316  		{itemString, "nats.io:-1", 1, 8},
  1317  		{itemEOF, "", 1, 0},
  1318  	}
  1319  	lx = lex("listen: nats.io:-1")
  1320  	expect(t, lx, expectedItems)
  1321  
  1322  	expectedItems = []item{
  1323  		{itemKey, "listen", 1, 0},
  1324  		{itemInteger, "-1", 1, 8},
  1325  		{itemEOF, "", 1, 0},
  1326  	}
  1327  	lx = lex("listen: -1")
  1328  	expect(t, lx, expectedItems)
  1329  
  1330  	expectedItems = []item{
  1331  		{itemKey, "listen", 1, 0},
  1332  		{itemString, ":-1", 1, 8},
  1333  		{itemEOF, "", 1, 0},
  1334  	}
  1335  	lx = lex("listen: :-1")
  1336  	expect(t, lx, expectedItems)
  1337  
  1338  	expectedItems = []item{
  1339  		{itemKey, "listen", 1, 0},
  1340  		{itemString, ":80", 1, 9},
  1341  		{itemEOF, "", 1, 0},
  1342  	}
  1343  	lx = lex("listen = :80")
  1344  	expect(t, lx, expectedItems)
  1345  
  1346  	expectedItems = []item{
  1347  		{itemKey, "listen", 1, 0},
  1348  		{itemArrayStart, "", 1, 10},
  1349  		{itemString, "localhost:4222", 1, 10},
  1350  		{itemString, "localhost:4333", 1, 26},
  1351  		{itemArrayEnd, "", 1, 41},
  1352  		{itemEOF, "", 1, 0},
  1353  	}
  1354  	lx = lex("listen = [localhost:4222, localhost:4333]")
  1355  	expect(t, lx, expectedItems)
  1356  }
  1357  
  1358  var arrayOfMaps = `
  1359  authorization {
  1360      users = [
  1361        {user: alice, password: foo}
  1362        {user: bob,   password: bar}
  1363      ]
  1364      timeout: 0.5
  1365  }
  1366  `
  1367  
  1368  func TestArrayOfMaps(t *testing.T) {
  1369  	expectedItems := []item{
  1370  		{itemKey, "authorization", 2, 1},
  1371  		{itemMapStart, "", 2, 16},
  1372  		{itemKey, "users", 3, 5},
  1373  		{itemArrayStart, "", 3, 14},
  1374  		{itemMapStart, "", 4, 8},
  1375  		{itemKey, "user", 4, 8},
  1376  		{itemString, "alice", 4, 14},
  1377  		{itemKey, "password", 4, 21},
  1378  		{itemString, "foo", 4, 31},
  1379  		{itemMapEnd, "", 4, 35},
  1380  		{itemMapStart, "", 5, 8},
  1381  		{itemKey, "user", 5, 8},
  1382  		{itemString, "bob", 5, 14},
  1383  		{itemKey, "password", 5, 21},
  1384  		{itemString, "bar", 5, 31},
  1385  		{itemMapEnd, "", 5, 35},
  1386  		{itemArrayEnd, "", 6, 6},
  1387  		{itemKey, "timeout", 7, 5},
  1388  		{itemFloat, "0.5", 7, 14},
  1389  		{itemMapEnd, "", 8, 2},
  1390  		{itemEOF, "", 9, 0},
  1391  	}
  1392  	lx := lex(arrayOfMaps)
  1393  	expect(t, lx, expectedItems)
  1394  }
  1395  
  1396  func TestInclude(t *testing.T) {
  1397  	expectedItems := []item{
  1398  		{itemInclude, "users.conf", 1, 9},
  1399  		{itemEOF, "", 1, 0},
  1400  	}
  1401  	lx := lex("include \"users.conf\"")
  1402  	expect(t, lx, expectedItems)
  1403  
  1404  	lx = lex("include 'users.conf'")
  1405  	expect(t, lx, expectedItems)
  1406  
  1407  	expectedItems = []item{
  1408  		{itemInclude, "users.conf", 1, 8},
  1409  		{itemEOF, "", 1, 0},
  1410  	}
  1411  	lx = lex("include users.conf")
  1412  	expect(t, lx, expectedItems)
  1413  }
  1414  
  1415  func TestMapInclude(t *testing.T) {
  1416  	expectedItems := []item{
  1417  		{itemKey, "foo", 1, 0},
  1418  		{itemMapStart, "", 1, 5},
  1419  		{itemInclude, "users.conf", 1, 14},
  1420  		{itemMapEnd, "", 1, 26},
  1421  		{itemEOF, "", 1, 0},
  1422  	}
  1423  
  1424  	lx := lex("foo { include users.conf }")
  1425  	expect(t, lx, expectedItems)
  1426  
  1427  	expectedItems = []item{
  1428  		{itemKey, "foo", 1, 0},
  1429  		{itemMapStart, "", 1, 5},
  1430  		{itemInclude, "users.conf", 1, 13},
  1431  		{itemMapEnd, "", 1, 24},
  1432  		{itemEOF, "", 1, 0},
  1433  	}
  1434  	lx = lex("foo {include users.conf}")
  1435  	expect(t, lx, expectedItems)
  1436  
  1437  	expectedItems = []item{
  1438  		{itemKey, "foo", 1, 0},
  1439  		{itemMapStart, "", 1, 5},
  1440  		{itemInclude, "users.conf", 1, 15},
  1441  		{itemMapEnd, "", 1, 28},
  1442  		{itemEOF, "", 1, 0},
  1443  	}
  1444  	lx = lex("foo { include 'users.conf' }")
  1445  	expect(t, lx, expectedItems)
  1446  
  1447  	expectedItems = []item{
  1448  		{itemKey, "foo", 1, 0},
  1449  		{itemMapStart, "", 1, 5},
  1450  		{itemInclude, "users.conf", 1, 15},
  1451  		{itemMapEnd, "", 1, 27},
  1452  		{itemEOF, "", 1, 0},
  1453  	}
  1454  	lx = lex("foo { include \"users.conf\"}")
  1455  	expect(t, lx, expectedItems)
  1456  }
  1457  
  1458  func TestJSONCompat(t *testing.T) {
  1459  	for _, test := range []struct {
  1460  		name     string
  1461  		input    string
  1462  		expected []item
  1463  	}{
  1464  		{
  1465  			name: "should omit initial and final brackets at top level with a single item",
  1466  			input: `
  1467                          {
  1468                            "http_port": 8223
  1469                          }
  1470                          `,
  1471  			expected: []item{
  1472  				{itemKey, "http_port", 3, 28},
  1473  				{itemInteger, "8223", 3, 40},
  1474  				{itemKey, "}", 4, 25},
  1475  				{itemEOF, "", 0, 0},
  1476  			},
  1477  		},
  1478  		{
  1479  			name: "should omit trailing commas at top level with two items",
  1480  			input: `
  1481                          {
  1482                            "http_port": 8223,
  1483                            "port": 4223
  1484                          }
  1485                          `,
  1486  			expected: []item{
  1487  				{itemKey, "http_port", 3, 28},
  1488  				{itemInteger, "8223", 3, 40},
  1489  				{itemKey, "port", 4, 28},
  1490  				{itemInteger, "4223", 4, 35},
  1491  				{itemKey, "}", 5, 25},
  1492  				{itemEOF, "", 0, 0},
  1493  			},
  1494  		},
  1495  		{
  1496  			name: "should omit trailing commas at top level with multiple items",
  1497  			input: `
  1498                          {
  1499                            "http_port": 8223,
  1500                            "port": 4223,
  1501                            "max_payload": "5MB",
  1502                            "debug": true,
  1503                            "max_control_line": 1024
  1504                          }
  1505                          `,
  1506  			expected: []item{
  1507  				{itemKey, "http_port", 3, 28},
  1508  				{itemInteger, "8223", 3, 40},
  1509  				{itemKey, "port", 4, 28},
  1510  				{itemInteger, "4223", 4, 35},
  1511  				{itemKey, "max_payload", 5, 28},
  1512  				{itemString, "5MB", 5, 43},
  1513  				{itemKey, "debug", 6, 28},
  1514  				{itemBool, "true", 6, 36},
  1515  				{itemKey, "max_control_line", 7, 28},
  1516  				{itemInteger, "1024", 7, 47},
  1517  				{itemKey, "}", 8, 25},
  1518  				{itemEOF, "", 0, 0},
  1519  			},
  1520  		},
  1521  		{
  1522  			name: "should support JSON not prettified",
  1523  			input: `{"http_port": 8224,"port": 4224}
  1524                          `,
  1525  			expected: []item{
  1526  				{itemKey, "http_port", 1, 2},
  1527  				{itemInteger, "8224", 1, 14},
  1528  				{itemKey, "port", 1, 20},
  1529  				{itemInteger, "4224", 1, 27},
  1530  				{itemEOF, "", 0, 0},
  1531  			},
  1532  		},
  1533  		{
  1534  			name: "should support JSON not prettified with final bracket after newline",
  1535  			input: `{"http_port": 8225,"port": 4225
  1536                          }
  1537                          `,
  1538  			expected: []item{
  1539  				{itemKey, "http_port", 1, 2},
  1540  				{itemInteger, "8225", 1, 14},
  1541  				{itemKey, "port", 1, 20},
  1542  				{itemInteger, "4225", 1, 27},
  1543  				{itemKey, "}", 2, 25},
  1544  				{itemEOF, "", 0, 0},
  1545  			},
  1546  		},
  1547  		{
  1548  			name: "should support uglified JSON with inner blocks",
  1549  			input: `{"http_port": 8227,"port": 4227,"write_deadline": "1h","cluster": {"port": 6222,"routes": ["nats://127.0.0.1:4222","nats://127.0.0.1:4223","nats://127.0.0.1:4224"]}}
  1550                          `,
  1551  			expected: []item{
  1552  				{itemKey, "http_port", 1, 2},
  1553  				{itemInteger, "8227", 1, 14},
  1554  				{itemKey, "port", 1, 20},
  1555  				{itemInteger, "4227", 1, 27},
  1556  				{itemKey, "write_deadline", 1, 33},
  1557  				{itemString, "1h", 1, 51},
  1558  				{itemKey, "cluster", 1, 56},
  1559  				{itemMapStart, "", 1, 67},
  1560  				{itemKey, "port", 1, 68},
  1561  				{itemInteger, "6222", 1, 75},
  1562  				{itemKey, "routes", 1, 81},
  1563  				{itemArrayStart, "", 1, 91},
  1564  				{itemString, "nats://127.0.0.1:4222", 1, 92},
  1565  				{itemString, "nats://127.0.0.1:4223", 1, 116},
  1566  				{itemString, "nats://127.0.0.1:4224", 1, 140},
  1567  				{itemArrayEnd, "", 1, 163},
  1568  				{itemMapEnd, "", 1, 164},
  1569  				{itemKey, "}", 14, 25},
  1570  				{itemEOF, "", 0, 0},
  1571  			},
  1572  		},
  1573  		{
  1574  			name: "should support prettified JSON with inner blocks",
  1575  			input: `
  1576                          {
  1577                            "http_port": 8227,
  1578                            "port": 4227,
  1579                            "write_deadline": "1h",
  1580                            "cluster": {
  1581                              "port": 6222,
  1582                              "routes": [
  1583                                "nats://127.0.0.1:4222",
  1584                                "nats://127.0.0.1:4223",
  1585                                "nats://127.0.0.1:4224"
  1586                              ]
  1587                            }
  1588                          }
  1589                          `,
  1590  			expected: []item{
  1591  				{itemKey, "http_port", 3, 28},
  1592  				{itemInteger, "8227", 3, 40},
  1593  				{itemKey, "port", 4, 28},
  1594  				{itemInteger, "4227", 4, 35},
  1595  				{itemKey, "write_deadline", 5, 28},
  1596  				{itemString, "1h", 5, 46},
  1597  				{itemKey, "cluster", 6, 28},
  1598  				{itemMapStart, "", 6, 39},
  1599  				{itemKey, "port", 7, 30},
  1600  				{itemInteger, "6222", 7, 37},
  1601  				{itemKey, "routes", 8, 30},
  1602  				{itemArrayStart, "", 8, 40},
  1603  				{itemString, "nats://127.0.0.1:4222", 9, 32},
  1604  				{itemString, "nats://127.0.0.1:4223", 10, 32},
  1605  				{itemString, "nats://127.0.0.1:4224", 11, 32},
  1606  				{itemArrayEnd, "", 12, 30},
  1607  				{itemMapEnd, "", 13, 28},
  1608  				{itemKey, "}", 14, 25},
  1609  				{itemEOF, "", 0, 0},
  1610  			},
  1611  		},
  1612  		{
  1613  			name: "should support JSON with blocks",
  1614  			input: `{
  1615                            "jetstream": {
  1616                              "store_dir": "/tmp/nats"
  1617                              "max_mem": 1000000,
  1618                            },
  1619                            "port": 4222,
  1620                            "server_name": "nats1"
  1621                          }
  1622                          `,
  1623  			expected: []item{
  1624  				{itemKey, "jetstream", 2, 28},
  1625  				{itemMapStart, "", 2, 41},
  1626  				{itemKey, "store_dir", 3, 30},
  1627  				{itemString, "/tmp/nats", 3, 43},
  1628  				{itemKey, "max_mem", 4, 30},
  1629  				{itemInteger, "1000000", 4, 40},
  1630  				{itemMapEnd, "", 5, 28},
  1631  				{itemKey, "port", 6, 28},
  1632  				{itemInteger, "4222", 6, 35},
  1633  				{itemKey, "server_name", 7, 28},
  1634  				{itemString, "nats1", 7, 43},
  1635  				{itemKey, "}", 8, 25},
  1636  				{itemEOF, "", 0, 0},
  1637  			},
  1638  		},
  1639  	} {
  1640  		t.Run(test.name, func(t *testing.T) {
  1641  			lx := lex(test.input)
  1642  			expect(t, lx, test.expected)
  1643  		})
  1644  	}
  1645  }