github.com/authzed/spicedb@v1.32.1-0.20240520085336-ebda56537386/pkg/schemadsl/compiler/development_test.go (about)

     1  package compiler
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/require"
     7  
     8  	"github.com/authzed/spicedb/pkg/schemadsl/dslshape"
     9  	"github.com/authzed/spicedb/pkg/schemadsl/input"
    10  )
    11  
    12  func TestPositionToAstNode(t *testing.T) {
    13  	tcs := []struct {
    14  		name          string
    15  		schema        string
    16  		line          int
    17  		column        int
    18  		expected      []dslshape.NodeType
    19  		expectedError string
    20  	}{
    21  		{
    22  			name:          "empty schema",
    23  			schema:        "",
    24  			line:          1,
    25  			column:        1,
    26  			expected:      nil,
    27  			expectedError: "unknown line 1 in source file",
    28  		},
    29  		{
    30  			name:     "single def",
    31  			schema:   `definition user {}`,
    32  			line:     0,
    33  			column:   0,
    34  			expected: []dslshape.NodeType{dslshape.NodeTypeDefinition, dslshape.NodeTypeFile},
    35  		},
    36  		{
    37  			name:     "single def, later on line",
    38  			schema:   `definition user {}`,
    39  			line:     0,
    40  			column:   10,
    41  			expected: []dslshape.NodeType{dslshape.NodeTypeDefinition, dslshape.NodeTypeFile},
    42  		},
    43  		{
    44  			name: "relation",
    45  			schema: `definition resource {
    46  				relation viewer: user
    47  			}`,
    48  			line:     1,
    49  			column:   10,
    50  			expected: []dslshape.NodeType{dslshape.NodeTypeRelation, dslshape.NodeTypeDefinition, dslshape.NodeTypeFile},
    51  		},
    52  		{
    53  			name: "relation subject type",
    54  			schema: `definition resource {
    55  				relation viewer: user
    56  			}`,
    57  			line:   1,
    58  			column: 22,
    59  			expected: []dslshape.NodeType{
    60  				dslshape.NodeTypeSpecificTypeReference,
    61  				dslshape.NodeTypeTypeReference,
    62  				dslshape.NodeTypeRelation,
    63  				dslshape.NodeTypeDefinition,
    64  				dslshape.NodeTypeFile,
    65  			},
    66  		},
    67  		{
    68  			name: "reference in permission",
    69  			schema: `definition resource {
    70  				relation viewer: user
    71  				permission view = viewer
    72  			}`,
    73  			line:   2,
    74  			column: 26,
    75  			expected: []dslshape.NodeType{
    76  				dslshape.NodeTypeIdentifier,
    77  				dslshape.NodeTypePermission,
    78  				dslshape.NodeTypeDefinition,
    79  				dslshape.NodeTypeFile,
    80  			},
    81  		},
    82  		{
    83  			name: "reference in union permission",
    84  			schema: `definition resource {
    85  				relation viewer: user
    86  				relation editor: user
    87  				permission view = viewer + editor
    88  			}`,
    89  			line:   3,
    90  			column: 34,
    91  			expected: []dslshape.NodeType{
    92  				dslshape.NodeTypeIdentifier,
    93  				dslshape.NodeTypeUnionExpression,
    94  				dslshape.NodeTypePermission,
    95  				dslshape.NodeTypeDefinition,
    96  				dslshape.NodeTypeFile,
    97  			},
    98  		},
    99  		{
   100  			name: "reference in caveat expression",
   101  			schema: `
   102  			caveat some_caveat(someparam int) {
   103  				someparam > 42
   104  			}
   105  
   106  			definition resource {
   107  				relation viewer: user
   108  				permission view = viewer
   109  			}`,
   110  			line:   2,
   111  			column: 6,
   112  			expected: []dslshape.NodeType{
   113  				dslshape.NodeTypeCaveatExpression,
   114  				dslshape.NodeTypeCaveatDefinition,
   115  				dslshape.NodeTypeFile,
   116  			},
   117  		},
   118  		{
   119  			name: "reference in caveat parameter",
   120  			schema: `
   121  			caveat some_caveat(someparam int) {
   122  				someparam > 42
   123  			}
   124  
   125  			definition resource {
   126  				relation viewer: user
   127  				permission view = viewer
   128  			}`,
   129  			line:   1,
   130  			column: 26,
   131  			expected: []dslshape.NodeType{
   132  				dslshape.NodeTypeCaveatParameter,
   133  				dslshape.NodeTypeCaveatDefinition,
   134  				dslshape.NodeTypeFile,
   135  			},
   136  		},
   137  		{
   138  			name: "reference in caveat parameter type",
   139  			schema: `
   140  			caveat some_caveat(someparam int) {
   141  				someparam > 42
   142  			}
   143  
   144  			definition resource {
   145  				relation viewer: user
   146  				permission view = viewer
   147  			}`,
   148  			line:   1,
   149  			column: 33,
   150  			expected: []dslshape.NodeType{
   151  				dslshape.NodeTypeCaveatTypeReference,
   152  				dslshape.NodeTypeCaveatParameter,
   153  				dslshape.NodeTypeCaveatDefinition,
   154  				dslshape.NodeTypeFile,
   155  			},
   156  		},
   157  		{
   158  			name: "reference to caveat",
   159  			schema: `
   160  			caveat some_caveat(someparam int) {
   161  				someparam > 42
   162  			}
   163  
   164  			definition resource {
   165  				relation viewer: user with some_caveat
   166  				permission view = viewer
   167  			}`,
   168  			line:   6,
   169  			column: 40,
   170  			expected: []dslshape.NodeType{
   171  				dslshape.NodeTypeCaveatReference,
   172  				dslshape.NodeTypeSpecificTypeReference,
   173  				dslshape.NodeTypeTypeReference,
   174  				dslshape.NodeTypeRelation,
   175  				dslshape.NodeTypeDefinition,
   176  				dslshape.NodeTypeFile,
   177  			},
   178  		},
   179  		{
   180  			name: "multiline doc comment",
   181  			schema: `
   182  				definition user {}
   183  
   184  				/**
   185  				 * This is a doc comment
   186  				 */
   187  				definition resource {
   188  					relation viewer: user
   189  				}
   190  			`,
   191  			line:   4,
   192  			column: 2,
   193  			expected: []dslshape.NodeType{
   194  				dslshape.NodeTypeFile,
   195  			},
   196  		},
   197  		{
   198  			name: "reference to commented",
   199  			schema: `
   200  				definition user {}
   201  
   202  				definition resource {
   203  					// viewer is some sort of relation
   204  					relation viewer: user
   205  				}
   206  			`,
   207  			line:   5,
   208  			column: 10,
   209  			expected: []dslshape.NodeType{
   210  				dslshape.NodeTypeRelation,
   211  				dslshape.NodeTypeDefinition,
   212  				dslshape.NodeTypeFile,
   213  			},
   214  		},
   215  	}
   216  
   217  	for _, tc := range tcs {
   218  		tc := tc
   219  		t.Run(tc.name, func(t *testing.T) {
   220  			t.Parallel()
   221  
   222  			compiled, err := Compile(InputSchema{
   223  				Source:       input.Source("test"),
   224  				SchemaString: tc.schema,
   225  			}, AllowUnprefixedObjectType())
   226  			require.NoError(t, err)
   227  
   228  			nodeChain, err := PositionToAstNodeChain(compiled, input.Source("test"), input.Position{
   229  				LineNumber:     tc.line,
   230  				ColumnPosition: tc.column,
   231  			})
   232  			if tc.expectedError != "" {
   233  				require.Error(t, err)
   234  				require.Contains(t, err.Error(), tc.expectedError)
   235  				return
   236  			}
   237  
   238  			require.NoError(t, err)
   239  
   240  			if tc.expected == nil {
   241  				require.Nil(t, nodeChain)
   242  			} else {
   243  				require.NotNil(t, nodeChain)
   244  				nodes := nodeChain.nodes
   245  
   246  				nodeTypes := make([]dslshape.NodeType, len(nodes))
   247  				for idx, node := range nodes {
   248  					nodeTypes[idx] = node.GetType()
   249  				}
   250  
   251  				require.Equal(t, tc.expected, nodeTypes)
   252  			}
   253  		})
   254  	}
   255  }