github.com/authzed/spicedb@v1.32.1-0.20240520085336-ebda56537386/pkg/validationfile/fileformat_test.go (about)

     1  package validationfile
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/require"
     7  
     8  	"github.com/authzed/spicedb/pkg/spiceerrors"
     9  )
    10  
    11  func TestDecodeValidationFile(t *testing.T) {
    12  	tests := []struct {
    13  		name                     string
    14  		contents                 string
    15  		expectedError            string
    16  		expectedRelCount         int
    17  		expectedAssertTrueCount  int
    18  		expectedAssertFalseCount int
    19  		expectedValidationCount  int
    20  	}{
    21  		{
    22  			name:                     "empty",
    23  			contents:                 "",
    24  			expectedError:            "",
    25  			expectedRelCount:         0,
    26  			expectedAssertTrueCount:  0,
    27  			expectedAssertFalseCount: 0,
    28  			expectedValidationCount:  0,
    29  		},
    30  		{
    31  			name: "invalid schema",
    32  			contents: `schema:
    33  foo:
    34  	- asdasd`,
    35  			expectedError:            "yaml: line 3: found character that cannot start any token",
    36  			expectedRelCount:         0,
    37  			expectedAssertTrueCount:  0,
    38  			expectedAssertFalseCount: 0,
    39  			expectedValidationCount:  0,
    40  		},
    41  		{
    42  			name: "valid",
    43  			contents: `
    44  schema: >-
    45    definition user {}
    46    definition document {
    47        relation writer: user
    48        relation reader: user
    49        permission edit = writer
    50        permission view = reader + edit
    51    }
    52  
    53  relationships: >-
    54    document:firstdoc#writer@user:tom
    55  
    56    document:firstdoc#reader@user:fred
    57  
    58    document:seconddoc#reader@user:tom
    59  
    60  assertions:
    61    assertTrue:
    62      - document:firstdoc#view@user:tom
    63      - document:firstdoc#view@user:fred
    64      - document:seconddoc#view@user:tom
    65    assertFalse:
    66      - document:seconddoc#view@user:fred
    67  
    68  validation:
    69    document:firstdoc#view:
    70      - "[user:tom] is <document:firstdoc#writer>"
    71      - "[user:fred] is <document:firstdoc#reader>"
    72    document:seconddoc#view:
    73      - "[user:tom] is <document:seconddoc#reader>"
    74  `,
    75  			expectedError:            "",
    76  			expectedRelCount:         3,
    77  			expectedAssertTrueCount:  3,
    78  			expectedAssertFalseCount: 1,
    79  			expectedValidationCount:  2,
    80  		},
    81  	}
    82  
    83  	for _, tt := range tests {
    84  		tt := tt
    85  		t.Run(tt.name, func(t *testing.T) {
    86  			decoded, err := DecodeValidationFile([]byte(tt.contents))
    87  			if tt.expectedError != "" {
    88  				require.NotNil(t, err)
    89  				require.Equal(t, err.Error(), tt.expectedError)
    90  			} else {
    91  				require.Nil(t, err)
    92  
    93  				require.NotNil(t, decoded)
    94  				require.Equal(t, len(decoded.Relationships.Relationships), tt.expectedRelCount)
    95  
    96  				require.Equal(t, len(decoded.Assertions.AssertTrue), tt.expectedAssertTrueCount)
    97  				require.Equal(t, len(decoded.Assertions.AssertFalse), tt.expectedAssertFalseCount)
    98  				require.Equal(t, len(decoded.ExpectedRelations.ValidationMap), tt.expectedValidationCount)
    99  			}
   100  		})
   101  	}
   102  }
   103  
   104  func TestDecodeRelationshipsErrorLineNumber(t *testing.T) {
   105  	_, err := DecodeValidationFile([]byte(`schema: >-
   106    definition user {}
   107  
   108  relationships: >-
   109    document:firstdocwriter@user:tom
   110  
   111    document:firstdoc#reader#user:fred
   112  `))
   113  
   114  	errWithSource, ok := spiceerrors.AsErrorWithSource(err)
   115  	require.True(t, ok)
   116  
   117  	require.Equal(t, err.Error(), "error parsing relationship `document:firstdocwriter@user:tom`")
   118  	require.Equal(t, uint64(5), errWithSource.LineNumber)
   119  }
   120  
   121  func TestDecodeRelationshipsErrorLineNumberLater(t *testing.T) {
   122  	_, err := DecodeValidationFile([]byte(`schema: >-
   123    definition user {}
   124  
   125  relationships: >-
   126    document:firstdoc#writer@user:tom
   127  
   128    document:firstdoc#readeruser:fred
   129  `))
   130  
   131  	errWithSource, ok := spiceerrors.AsErrorWithSource(err)
   132  	require.True(t, ok)
   133  
   134  	require.Equal(t, err.Error(), "error parsing relationship `document:firstdoc#readeruser:fred`")
   135  	require.Equal(t, uint64(7), errWithSource.LineNumber)
   136  }
   137  
   138  func TestDecodeRelationshipsErrorLineNumberEventLater(t *testing.T) {
   139  	_, err := DecodeValidationFile([]byte(`schema: >-
   140    definition user {}
   141  
   142  relationships: >-
   143    document:firstdoc#writer@user:tom1
   144  
   145    document:firstdoc#writer@user:tom2
   146  
   147    document:firstdoc#writer@user:tom3
   148  
   149    document:firstdoc#writer@user:tom4
   150  
   151    document:firstdoc#readeruser:fred
   152  `))
   153  
   154  	errWithSource, ok := spiceerrors.AsErrorWithSource(err)
   155  	require.True(t, ok)
   156  
   157  	require.Equal(t, err.Error(), "error parsing relationship `document:firstdoc#readeruser:fred`")
   158  	require.Equal(t, uint64(13), errWithSource.LineNumber)
   159  }
   160  
   161  func TestDecodeAssertionsErrorLineNumber(t *testing.T) {
   162  	_, err := DecodeValidationFile([]byte(`
   163  schema: >-
   164    definition user {}
   165  
   166  relationships: >-
   167    document:firstdoc#writer@user:tom
   168  
   169  assertions:
   170    assertTrue: asdkjhasd
   171      - document:firstdoc#view@user:tom
   172      - document:firstdoc#view@user:fred
   173      - document:seconddoc#view@user:tom
   174    assertFalse:
   175      - document:seconddoc#view@user:fred
   176  `))
   177  
   178  	errWithSource, ok := spiceerrors.AsErrorWithSource(err)
   179  	require.True(t, ok)
   180  
   181  	require.Equal(t, err.Error(), "unexpected value `asdkjha`")
   182  	require.Equal(t, uint64(9), errWithSource.LineNumber)
   183  }
   184  
   185  func TestDecodeAssertionsErrorLineNumberSmallerToken(t *testing.T) {
   186  	_, err := DecodeValidationFile([]byte(`
   187  schema: >-
   188    definition user {}
   189  
   190  relationships: >-
   191    document:firstdoc#writer@user:tom
   192  
   193  assertions:
   194    assertTrue: asdk
   195      - document:firstdoc#view@user:tom
   196      - document:firstdoc#view@user:fred
   197      - document:seconddoc#view@user:tom
   198    assertFalse:
   199      - document:seconddoc#view@user:fred
   200  `))
   201  
   202  	errWithSource, ok := spiceerrors.AsErrorWithSource(err)
   203  	require.True(t, ok)
   204  
   205  	require.Equal(t, err.Error(), "unexpected value `asdk`")
   206  	require.Equal(t, uint64(9), errWithSource.LineNumber)
   207  }