...

Source file src/github.com/launchdarkly/go-sdk-common/v3/ldattr/ref_test.go

Documentation: github.com/launchdarkly/go-sdk-common/v3/ldattr

     1  package ldattr
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"testing"
     7  
     8  	"github.com/launchdarkly/go-sdk-common/v3/lderrors"
     9  
    10  	"github.com/stretchr/testify/assert"
    11  )
    12  
    13  func TestRefInvalid(t *testing.T) {
    14  	for _, p := range []struct {
    15  		input         string
    16  		expectedError error
    17  	}{
    18  		{"", lderrors.ErrAttributeEmpty{}},
    19  		{"/", lderrors.ErrAttributeEmpty{}},
    20  		{"//", lderrors.ErrAttributeExtraSlash{}},
    21  		{"/a//b", lderrors.ErrAttributeExtraSlash{}},
    22  		{"/a/b/", lderrors.ErrAttributeExtraSlash{}},
    23  		{"/a~x", lderrors.ErrAttributeInvalidEscape{}},
    24  		{"/a~", lderrors.ErrAttributeInvalidEscape{}},
    25  		{"/a/b~x", lderrors.ErrAttributeInvalidEscape{}},
    26  		{"/a/b~", lderrors.ErrAttributeInvalidEscape{}},
    27  	} {
    28  		t.Run(fmt.Sprintf("input string %q", p.input), func(t *testing.T) {
    29  			a := NewRef(p.input)
    30  			assert.True(t, a.IsDefined())
    31  			assert.Equal(t, p.expectedError, a.Err())
    32  			assert.Equal(t, p.input, a.String())
    33  			assert.Equal(t, 0, a.Depth())
    34  		})
    35  	}
    36  
    37  	t.Run("uninitialized", func(t *testing.T) {
    38  		var a Ref
    39  		assert.False(t, a.IsDefined())
    40  		assert.Equal(t, lderrors.ErrAttributeEmpty{}, a.Err())
    41  		assert.Equal(t, "", a.String())
    42  		assert.Equal(t, 0, a.Depth())
    43  	})
    44  }
    45  
    46  func TestRefWithNoLeadingSlash(t *testing.T) {
    47  	for _, s := range []string{
    48  		"key",
    49  		"kind",
    50  		"name",
    51  		"name/with/slashes",
    52  		"name~0~1with-what-looks-like-escape-sequences",
    53  	} {
    54  		t.Run(fmt.Sprintf("input string %q", s), func(t *testing.T) {
    55  			a := NewRef(s)
    56  			assert.True(t, a.IsDefined())
    57  			assert.NoError(t, a.Err())
    58  			assert.Equal(t, s, a.String())
    59  			assert.Equal(t, 1, a.Depth())
    60  			assert.Equal(t, s, a.Component(0))
    61  		})
    62  	}
    63  }
    64  
    65  func TestRefSimpleWithLeadingSlash(t *testing.T) {
    66  	for _, params := range []struct {
    67  		input string
    68  		path  string
    69  	}{
    70  		{"/key", "key"},
    71  		{"/kind", "kind"},
    72  		{"/name", "name"},
    73  		{"/custom", "custom"},
    74  		{"/0", "0"},
    75  		{"/name~1with~1slashes~0and~0tildes", "name/with/slashes~and~tildes"},
    76  	} {
    77  		t.Run(fmt.Sprintf("input string %q", params.input), func(t *testing.T) {
    78  			a := NewRef(params.input)
    79  			assert.True(t, a.IsDefined())
    80  			assert.NoError(t, a.Err())
    81  			assert.Equal(t, params.input, a.String())
    82  			assert.Equal(t, 1, a.Depth())
    83  			assert.Equal(t, params.path, a.Component(0))
    84  		})
    85  	}
    86  }
    87  
    88  func TestNewLiteralRef(t *testing.T) {
    89  	a0 := NewLiteralRef("name")
    90  	assert.Equal(t, NewRef("name"), a0)
    91  
    92  	a1 := NewLiteralRef("a/b")
    93  	assert.Equal(t, NewRef("a/b"), a1)
    94  
    95  	a2 := NewLiteralRef("/a/b~c")
    96  	assert.Equal(t, NewRef("/~1a~1b~0c"), a2)
    97  	assert.Equal(t, 1, a2.Depth())
    98  
    99  	a3 := NewLiteralRef("/")
   100  	assert.Equal(t, NewRef("/~1"), a3)
   101  	assert.Equal(t, 1, a3.Depth())
   102  
   103  	a4 := NewLiteralRef("")
   104  	assert.Equal(t, lderrors.ErrAttributeEmpty{}, a4.Err())
   105  }
   106  
   107  func TestRefComponents(t *testing.T) {
   108  	for _, params := range []struct {
   109  		input        string
   110  		depth        int
   111  		index        int
   112  		expectedName string
   113  	}{
   114  		{"", 0, 0, ""},
   115  		{"key", 1, 0, "key"},
   116  		{"/key", 1, 0, "key"},
   117  		{"/a/b", 2, 0, "a"},
   118  		{"/a/b", 2, 1, "b"},
   119  		{"/a~1b/c", 2, 0, "a/b"},
   120  		{"/a~0b/c", 2, 0, "a~b"},
   121  		{"/a/10/20/30x", 4, 1, "10"},
   122  		{"/a/10/20/30x", 4, 2, "20"},
   123  		{"/a/10/20/30x", 4, 3, "30x"},
   124  
   125  		// invalid arguments don't cause an error, they just return empty values
   126  		{"", 0, -1, ""},
   127  		{"key", 1, -1, ""},
   128  		{"key", 1, 1, ""},
   129  		{"/key", 1, -1, ""},
   130  		{"/key", 1, 1, ""},
   131  		{"/a/b", 2, -1, ""},
   132  		{"/a/b", 2, 2, ""},
   133  	} {
   134  		t.Run(fmt.Sprintf("input string %q, index %d", params.input, params.index), func(t *testing.T) {
   135  			a := NewRef(params.input)
   136  			assert.Equal(t, params.depth, a.Depth())
   137  			name := a.Component(params.index)
   138  			assert.Equal(t, params.expectedName, name)
   139  		})
   140  	}
   141  }
   142  
   143  func TestRefEqual(t *testing.T) {
   144  	refs := []Ref{
   145  		{},
   146  		NewRef(""),
   147  		NewRef("a"),
   148  		NewRef("b"),
   149  		NewRef("/a/b"),
   150  		NewRef("/a/c"),
   151  		NewRef("///"),
   152  	}
   153  	for i, a := range refs {
   154  		sameValue := a
   155  		assert.True(t, sameValue.Equal(a))
   156  		for j, differentValue := range refs {
   157  			if j == i {
   158  				continue
   159  			}
   160  			assert.False(t, differentValue.Equal(a))
   161  		}
   162  	}
   163  }
   164  
   165  func TestRefMarshalJSON(t *testing.T) {
   166  	for _, p := range []struct {
   167  		ref  Ref
   168  		json string
   169  	}{
   170  		{Ref{}, `null`},
   171  		{NewRef("a"), `"a"`},
   172  		{NewRef("/a/b"), `"/a/b"`},
   173  		{NewRef("////invalid"), `"////invalid"`},
   174  	} {
   175  		t.Run(p.json, func(t *testing.T) {
   176  			bytes, err := json.Marshal(p.ref)
   177  			assert.NoError(t, err)
   178  			assert.Equal(t, p.json, string(bytes))
   179  		})
   180  	}
   181  }
   182  
   183  func TestRefUnmarshalJSON(t *testing.T) {
   184  	for _, p := range []struct {
   185  		json    string
   186  		ref     Ref
   187  		success bool
   188  	}{
   189  		{`null`, Ref{}, true},
   190  		{`"a"`, NewRef("a"), true},
   191  		{`"/a/b"`, NewRef("/a/b"), true},
   192  		{`"////invalid"`, NewRef("////invalid"), true},
   193  		{`true`, Ref{}, false},
   194  		{`2`, Ref{}, false},
   195  		{`[]`, Ref{}, false},
   196  		{`{}`, Ref{}, false},
   197  		{`.`, Ref{}, false},
   198  		{``, Ref{}, false},
   199  	} {
   200  		t.Run(p.json, func(t *testing.T) {
   201  			var ref Ref
   202  			err := json.Unmarshal([]byte(p.json), &ref)
   203  			assert.Equal(t, p.ref, ref)
   204  			if p.success {
   205  				assert.NoError(t, err)
   206  			} else {
   207  				assert.Error(t, err)
   208  			}
   209  		})
   210  	}
   211  }
   212  

View as plain text