github.com/grailbio/base@v0.0.11/config/parse_test.go (about)

     1  // Copyright 2019 GRAIL, Inc. All rights reserved.
     2  // Use of this source code is governed by the Apache 2.0
     3  // license that can be found in the LICENSE file.
     4  
     5  package config
     6  
     7  import (
     8  	"strings"
     9  	"testing"
    10  )
    11  
    12  // TestParseEmpty verifies that parsing a (logically) empty file is valid.
    13  func TestParseEmpty(t *testing.T) {
    14  	for _, c := range []struct {
    15  		name string
    16  		text string
    17  	}{
    18  		{"Empty", ""},
    19  		{"Whitespace", "\t\n \n\t  \n"},
    20  		{"Semicolons", ";;"},
    21  		{"Mix", " \t \n \n;\n ;"},
    22  	} {
    23  		t.Run(c.name, func(t *testing.T) {
    24  			instances, err := parse(strings.NewReader(c.text))
    25  			if err != nil {
    26  				t.Fatal(err)
    27  			}
    28  			if got, want := len(instances), 0; got != want {
    29  				t.Errorf("got %v, want %v", got, want)
    30  			}
    31  		})
    32  	}
    33  }
    34  
    35  func TestParse(t *testing.T) {
    36  	got, err := parse(strings.NewReader(strings.ReplaceAll(`
    37  param x y = "okay"
    38  param y z = 123
    39  param y a = "a"; param y b = b
    40  param y c = nil
    41  
    42  param y (
    43  	x = "blah"
    44  	y = 333
    45  	fprec = 0.123456789
    46  	raw = ${"it's json":
    47  12.3}$
    48  )
    49  
    50  instance z blah (
    51  	bloop = 123
    52  	negint = -3
    53  	negfloat = -3.14
    54  )
    55  
    56  param z x = 89898
    57  
    58  instance bigslice/system blah (
    59  	region = "us-west-2"
    60  )
    61  
    62  param zero-params ()
    63  `, "$", "`")))
    64  	if err != nil {
    65  		t.Fatal(err)
    66  	}
    67  	want := instances{
    68  		"x": &instance{
    69  			name: "x",
    70  			params: map[string]interface{}{
    71  				"y": "okay",
    72  			},
    73  		},
    74  		"y": &instance{
    75  			name: "y",
    76  			params: map[string]interface{}{
    77  				"x":     "blah",
    78  				"y":     333,
    79  				"z":     123,
    80  				"a":     "a",
    81  				"b":     indirect("b"),
    82  				"c":     indirect(""),
    83  				"fprec": 0.123456789,
    84  				"raw": `{"it's json":
    85  12.3}`,
    86  			},
    87  		},
    88  		"z": &instance{
    89  			name:   "z",
    90  			parent: "blah",
    91  			params: map[string]interface{}{
    92  				"bloop":    123,
    93  				"x":        89898,
    94  				"negint":   -3,
    95  				"negfloat": -3.14,
    96  			},
    97  		},
    98  		"bigslice/system": &instance{
    99  			name:   "bigslice/system",
   100  			parent: "blah",
   101  			params: map[string]interface{}{
   102  				"region": "us-west-2",
   103  			},
   104  		},
   105  		"zero-params": &instance{
   106  			name:   "zero-params",
   107  			parent: "",
   108  			params: map[string]interface{}{},
   109  		},
   110  	}
   111  	if !got.Equal(want) {
   112  		t.Errorf("got %v, want %v", got, want)
   113  	}
   114  	for name, wantInst := range want {
   115  		t.Run(name, func(t *testing.T) {
   116  			syntax := wantInst.SyntaxString(nil)
   117  			insts, err := parse(strings.NewReader(syntax))
   118  			if err != nil {
   119  				t.Fatalf("%v. syntax:\n%s", err, syntax)
   120  			}
   121  			if gotInst := insts[wantInst.name]; !wantInst.Equal(gotInst) {
   122  				t.Errorf("got %v, want %v, syntax:\n%s", got, want, syntax)
   123  			}
   124  		})
   125  	}
   126  }
   127  
   128  func TestParseError(t *testing.T) {
   129  	testError(t, `parm x y = 1`, `parse error: <input>:1:1: unrecognized toplevel clause: parm`)
   130  	testError(t, `param x _y = "hey"`, `parse error: <input>:1:9: unexpected: "_"`)
   131  	testError(t, `param x 123 = blah`, `parse error: <input>:1:9: unexpected: Int`)
   132  	testError(t, `param x y z`, `parse error: <input>:1:11: expected "="`)
   133  }
   134  
   135  func testError(t *testing.T, s, expect string) {
   136  	t.Helper()
   137  	_, err := parse(strings.NewReader(s))
   138  	if err == nil {
   139  		t.Error("expected error")
   140  		return
   141  	}
   142  	if got, want := err.Error(), expect; got != want {
   143  		t.Errorf("got %q, want %q", got, want)
   144  	}
   145  }