github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/internal/tiltfile/encoding/yaml_test.go (about)

     1  package encoding
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/require"
     8  
     9  	"github.com/tilt-dev/tilt/internal/testutils"
    10  	"github.com/tilt-dev/tilt/internal/tiltfile/io"
    11  )
    12  
    13  func TestReadYAML(t *testing.T) {
    14  	f := newFixture(t)
    15  
    16  	var document = `
    17  key1: foo
    18  key2:
    19      key3: "bar"
    20      key4: true
    21  key5: 3
    22  `
    23  	f.File("options.yaml", document)
    24  	f.File("Tiltfile", `
    25  observed = read_yaml("options.yaml")
    26  
    27  expected = {
    28    'key1': 'foo',
    29    'key2': {
    30      'key3': 'bar',
    31      'key4': True
    32    },
    33    'key5': 3,
    34  }
    35  
    36  load('assert.tilt', 'assert')
    37  assert.equals(expected, observed)
    38  `)
    39  
    40  	result, err := f.ExecFile("Tiltfile")
    41  	if err != nil {
    42  		fmt.Println(f.PrintOutput())
    43  	}
    44  	require.NoError(t, err)
    45  
    46  	rs, err := io.GetState(result)
    47  	require.NoError(t, err)
    48  	require.Contains(t, rs.Paths, f.JoinPath("options.yaml"))
    49  }
    50  
    51  func TestReadYAMLDefaultValue(t *testing.T) {
    52  	f := newFixture(t)
    53  
    54  	f.File("Tiltfile", `
    55  result = read_yaml("dne.yaml", "hello")
    56  
    57  load('assert.tilt', 'assert')
    58  assert.equals('hello', result)
    59  `)
    60  
    61  	_, err := f.ExecFile("Tiltfile")
    62  	if err != nil {
    63  		fmt.Println(f.PrintOutput())
    64  	}
    65  	require.NoError(t, err)
    66  }
    67  
    68  func TestReadYAMLStreamDefaultValue(t *testing.T) {
    69  	f := newFixture(t)
    70  
    71  	f.File("Tiltfile", `
    72  result = read_yaml_stream("dne.yaml", ["hello", "goodbye"])
    73  
    74  load('assert.tilt', 'assert')
    75  assert.equals(['hello', 'goodbye'], result)
    76  `)
    77  
    78  	_, err := f.ExecFile("Tiltfile")
    79  	if err != nil {
    80  		fmt.Println(f.PrintOutput())
    81  	}
    82  	require.NoError(t, err)
    83  }
    84  
    85  func TestYAMLDoesNotExist(t *testing.T) {
    86  	f := newFixture(t)
    87  
    88  	f.File("Tiltfile", `result = read_yaml("dne.yaml")`)
    89  	result, err := f.ExecFile("Tiltfile")
    90  	require.Error(t, err)
    91  	require.Contains(t, err.Error(), "dne.yaml")
    92  	testutils.AssertIsNotExist(t, err)
    93  
    94  	rs, err := io.GetState(result)
    95  	require.NoError(t, err)
    96  	require.Contains(t, rs.Paths, f.JoinPath("dne.yaml"))
    97  }
    98  
    99  func TestMalformedYAML(t *testing.T) {
   100  	f := newFixture(t)
   101  
   102  	f.UseRealFS()
   103  
   104  	var document = `
   105  key1: foo
   106  key2:
   107      key3: "bar
   108      key4: true
   109  key5: 3
   110  `
   111  	f.File("options.yaml", document)
   112  
   113  	f.File("Tiltfile", `result = read_yaml("options.yaml")`)
   114  	result, err := f.ExecFile("Tiltfile")
   115  	require.Error(t, err)
   116  	require.Contains(t, err.Error(), "error parsing YAML from options.yaml: error converting YAML to JSON: yaml: line 7: found unexpected end of stream")
   117  
   118  	rs, err := io.GetState(result)
   119  	require.NoError(t, err)
   120  	require.Contains(t, rs.Paths, f.JoinPath("options.yaml"))
   121  
   122  }
   123  
   124  func TestDecodeYAMLDocument(t *testing.T) {
   125  	for _, blob := range []bool{false, true} {
   126  		t.Run(fmt.Sprintf("blob: %v", blob), func(t *testing.T) {
   127  			f := newFixture(t)
   128  
   129  			d := `'- "foo"\n- baz:\n  - "bar"\n  - ""\n  - 1\n  - 2'`
   130  			if blob {
   131  				d = fmt.Sprintf("blob(%s)", d)
   132  			}
   133  			d = fmt.Sprintf("observed = decode_yaml(%s)", d)
   134  			tf := d + `
   135  expected = [
   136    "foo",
   137    {
   138      "baz": [ "bar", "", 1, 2],
   139    }
   140  ]
   141  
   142  load('assert.tilt', 'assert')
   143  assert.equals(expected, observed)
   144  `
   145  			f.File("Tiltfile", tf)
   146  
   147  			_, err := f.ExecFile("Tiltfile")
   148  			if err != nil {
   149  				fmt.Println(f.PrintOutput())
   150  			}
   151  			require.NoError(t, err)
   152  		})
   153  	}
   154  }
   155  
   156  func TestDecodeYAMLEmptyString(t *testing.T) {
   157  	f := newFixture(t)
   158  
   159  	tf := `
   160  observed = decode_yaml('')
   161  expected = None
   162  
   163  load('assert.tilt', 'assert')
   164  assert.equals(expected, observed)
   165  `
   166  	f.File("Tiltfile", tf)
   167  
   168  	_, err := f.ExecFile("Tiltfile")
   169  	if err != nil {
   170  		fmt.Println(f.PrintOutput())
   171  	}
   172  	require.NoError(t, err)
   173  }
   174  
   175  const yamlStream = `- foo
   176  - baz:
   177    - bar
   178    - ""
   179    - 1
   180    - 2
   181  ---
   182  quu:
   183  - qux
   184  - a:
   185    - 3
   186  `
   187  
   188  const yamlStreamAsStarlark = `[
   189    [
   190      "foo",
   191      {
   192        "baz": [ "bar", "", 1, 2],
   193      }
   194    ],
   195    {
   196      "quu": [
   197        "qux",
   198        {
   199  		"a": [3],
   200        }
   201      ]
   202    },
   203  ]`
   204  
   205  func TestReadYAMLStream(t *testing.T) {
   206  	f := newFixture(t)
   207  
   208  	f.UseRealFS()
   209  
   210  	f.File("test.yaml", yamlStream)
   211  	d := "observed = read_yaml_stream('test.yaml')\n"
   212  	d += fmt.Sprintf("expected = %s\n", yamlStreamAsStarlark)
   213  	tf := d + `
   214  def test():
   215  	if expected != observed:
   216  		print('expected: %s' % (expected))
   217  		print('observed: %s' % (observed))
   218  		fail()
   219  
   220  test()
   221  
   222  `
   223  	f.File("Tiltfile", tf)
   224  
   225  	_, err := f.ExecFile("Tiltfile")
   226  	if err != nil {
   227  		fmt.Println(f.PrintOutput())
   228  	}
   229  	require.NoError(t, err)
   230  }
   231  
   232  // call read_yaml on a stream, get an error
   233  func TestReadYAMLUnexpectedStream(t *testing.T) {
   234  	f := newFixture(t)
   235  
   236  	f.UseRealFS()
   237  
   238  	f.File("test.yaml", yamlStream)
   239  	tf := "observed = read_yaml('test.yaml')\n"
   240  	f.File("Tiltfile", tf)
   241  
   242  	_, err := f.ExecFile("Tiltfile")
   243  	if err != nil {
   244  		fmt.Println(f.PrintOutput())
   245  	}
   246  	require.Error(t, err)
   247  	require.Contains(t, err.Error(), "expected a yaml document but found a yaml stream")
   248  }
   249  
   250  func TestDecodeYAMLStream(t *testing.T) {
   251  	f := newFixture(t)
   252  
   253  	d := yamlStream
   254  	d = fmt.Sprintf("observed = decode_yaml_stream('''%s''')\n", d)
   255  	d += fmt.Sprintf("expected = %s\n", yamlStreamAsStarlark)
   256  	tf := d + `
   257  load('assert.tilt', 'assert')
   258  assert.equals(expected, observed)
   259  
   260  `
   261  	f.File("Tiltfile", tf)
   262  
   263  	_, err := f.ExecFile("Tiltfile")
   264  	if err != nil {
   265  		fmt.Println(f.PrintOutput())
   266  	}
   267  	require.NoError(t, err)
   268  }
   269  
   270  func TestDecodeYAMLStreamEmptyEntries(t *testing.T) {
   271  	f := newFixture(t)
   272  
   273  	yaml := `name: hello
   274  ---
   275  
   276  ---
   277  name: goodbye
   278  ---
   279  
   280  ---`
   281  	d := fmt.Sprintf("observed = decode_yaml_stream('''%s''')\n", yaml)
   282  	tf := d + `
   283  load('assert.tilt', 'assert')
   284  assert.equals(['hello', 'goodbye'], [r['name'] for r in observed])
   285  
   286  `
   287  	f.File("Tiltfile", tf)
   288  
   289  	_, err := f.ExecFile("Tiltfile")
   290  	if err != nil {
   291  		fmt.Println(f.PrintOutput())
   292  	}
   293  	require.NoError(t, err)
   294  }
   295  
   296  func TestDecodeYAMLUnexpectedStream(t *testing.T) {
   297  	f := newFixture(t)
   298  
   299  	tf := fmt.Sprintf("observed = decode_yaml('''%s''')\n", yamlStream)
   300  	f.File("Tiltfile", tf)
   301  
   302  	_, err := f.ExecFile("Tiltfile")
   303  	if err != nil {
   304  		fmt.Println(f.PrintOutput())
   305  	}
   306  	require.Error(t, err)
   307  	require.Contains(t, err.Error(), "expected a yaml document but found a yaml stream")
   308  }
   309  
   310  func TestEncodeYAML(t *testing.T) {
   311  	f := newFixture(t)
   312  
   313  	f.File("Tiltfile", `
   314  expected = '''key1: foo
   315  key2:
   316    key3: bar
   317    key4: true
   318  key5: 3
   319  key6:
   320  - foo
   321  - 7
   322  key7: []
   323  '''
   324  observed = encode_yaml({
   325    'key1': 'foo',
   326    'key2': {
   327      'key3': 'bar',
   328      'key4': True
   329    },
   330    'key5': 3,
   331    'key6': [
   332      'foo',
   333      7,
   334    ],
   335    'key7': []
   336  })
   337  
   338  load('assert.tilt', 'assert')
   339  assert.equals(expected, str(observed))
   340  `)
   341  
   342  	_, err := f.ExecFile("Tiltfile")
   343  	if err != nil {
   344  		fmt.Println(f.PrintOutput())
   345  	}
   346  	require.NoError(t, err)
   347  }
   348  
   349  func TestEncodeYAMLStream(t *testing.T) {
   350  	f := newFixture(t)
   351  
   352  	tf := fmt.Sprintf("expected = '''%s'''\n", yamlStream)
   353  	tf += fmt.Sprintf("observed = encode_yaml_stream(%s)\n", yamlStreamAsStarlark)
   354  	tf += `
   355  load('assert.tilt', 'assert')
   356  assert.equals(expected, str(observed))
   357  `
   358  
   359  	f.File("Tiltfile", tf)
   360  
   361  	_, err := f.ExecFile("Tiltfile")
   362  	if err != nil {
   363  		fmt.Println(f.PrintOutput())
   364  	}
   365  	require.NoError(t, err)
   366  }
   367  
   368  func TestEncodeYAMLNonStringMapKey(t *testing.T) {
   369  	f := newFixture(t)
   370  
   371  	f.File("Tiltfile", `encode_yaml({1: 'hello'})`)
   372  
   373  	_, err := f.ExecFile("Tiltfile")
   374  	require.Error(t, err)
   375  	require.Contains(t, err.Error(), "only string keys are supported in maps. found key '1' of type int64")
   376  }
   377  
   378  func TestEncodeYAMLNonYAMLable(t *testing.T) {
   379  	f := newFixture(t)
   380  
   381  	f.File("Tiltfile", `
   382  encode_yaml(blob('hello'))
   383  `)
   384  
   385  	_, err := f.ExecFile("Tiltfile")
   386  	require.Error(t, err)
   387  	require.Contains(t, err.Error(), "unsupported type io.Blob")
   388  }
   389  
   390  func TestDecodeYAMLIntFloat(t *testing.T) {
   391  	f := newFixture(t)
   392  	f.File("Tiltfile", `
   393  yaml = '''---
   394  int: 42
   395  float: 3.14
   396  '''
   397  x = decode_yaml(yaml)
   398  if repr(x["int"]) != "42":
   399    fail('repr(int) value was not "42": ' + repr(x["int"]))
   400  if repr(x["float"]) != "3.14":
   401    fail('repr(float) value was not a "3.14": ' + repr(x["float"]))
   402  `)
   403  
   404  	_, err := f.ExecFile("Tiltfile")
   405  	if err != nil {
   406  		fmt.Println(f.PrintOutput())
   407  	}
   408  	require.NoError(t, err)
   409  }