github.com/authzed/spicedb@v1.32.1-0.20240520085336-ebda56537386/pkg/development/resolver_test.go (about) 1 package development 2 3 import ( 4 "testing" 5 6 "github.com/stretchr/testify/require" 7 8 "github.com/authzed/spicedb/pkg/schemadsl/compiler" 9 "github.com/authzed/spicedb/pkg/schemadsl/input" 10 ) 11 12 func TestResolver(t *testing.T) { 13 testSource := input.Source("test") 14 15 tcs := []struct { 16 name string 17 schema string 18 line int 19 column int 20 expectedReference *SchemaReference 21 }{ 22 { 23 name: "basic relation", 24 schema: `definition user {} 25 26 definition resource { 27 relation viewer: user 28 permission view = viewer 29 } 30 `, 31 line: 4, 32 column: 24, 33 expectedReference: &SchemaReference{ 34 Source: input.Source("test"), 35 Position: input.Position{LineNumber: 4, ColumnPosition: 24}, 36 Text: "viewer", 37 ReferenceType: ReferenceTypeRelation, 38 ReferenceMarkdown: "relation viewer", 39 TargetSource: &testSource, 40 TargetPosition: &input.Position{LineNumber: 3, ColumnPosition: 4}, 41 TargetSourceCode: "relation viewer: user\n", 42 TargetNamePositionOffset: 9, 43 }, 44 }, 45 { 46 name: "basic permission", 47 schema: `definition user {} 48 49 definition resource { 50 relation viewer: user 51 relation editor: user 52 permission edit = editor 53 permission view = viewer + edit 54 } 55 `, 56 line: 6, 57 column: 33, 58 expectedReference: &SchemaReference{ 59 Source: input.Source("test"), 60 Position: input.Position{LineNumber: 6, ColumnPosition: 33}, 61 Text: "edit", 62 ReferenceType: ReferenceTypePermission, 63 ReferenceMarkdown: "permission edit", 64 TargetSource: &testSource, 65 TargetPosition: &input.Position{LineNumber: 5, ColumnPosition: 4}, 66 TargetSourceCode: "permission edit = editor\n", 67 TargetNamePositionOffset: 11, 68 }, 69 }, 70 { 71 name: "basic type", 72 schema: `definition user {} 73 74 definition resource { 75 relation viewer: user 76 permission view = viewer 77 } 78 `, 79 line: 3, 80 column: 24, 81 expectedReference: &SchemaReference{ 82 Source: input.Source("test"), 83 Position: input.Position{LineNumber: 3, ColumnPosition: 24}, 84 Text: "user", 85 ReferenceType: ReferenceTypeDefinition, 86 ReferenceMarkdown: "definition user", 87 TargetSource: &testSource, 88 TargetPosition: &input.Position{LineNumber: 0, ColumnPosition: 0}, 89 TargetSourceCode: "definition user {}", 90 TargetNamePositionOffset: 11, 91 }, 92 }, 93 { 94 name: "subject relation type", 95 schema: `definition user {} 96 97 definition group { 98 relation member: user 99 } 100 101 definition resource { 102 relation viewer: group#member 103 permission view = viewer 104 } 105 `, 106 line: 7, 107 column: 24, 108 expectedReference: &SchemaReference{ 109 Source: input.Source("test"), 110 Position: input.Position{LineNumber: 7, ColumnPosition: 24}, 111 Text: "group", 112 ReferenceType: ReferenceTypeDefinition, 113 ReferenceMarkdown: "definition group", 114 TargetSource: &testSource, 115 TargetPosition: &input.Position{LineNumber: 2, ColumnPosition: 3}, 116 TargetSourceCode: "definition group {\n\t// ...\n}", 117 TargetNamePositionOffset: 11, 118 }, 119 }, 120 { 121 name: "subject relation relation", 122 schema: `definition user {} 123 124 definition group { 125 relation member: user 126 } 127 128 definition resource { 129 relation viewer: group#member 130 permission view = viewer 131 } 132 `, 133 line: 7, 134 column: 32, 135 expectedReference: &SchemaReference{ 136 Source: input.Source("test"), 137 Position: input.Position{LineNumber: 7, ColumnPosition: 32}, 138 Text: "member", 139 ReferenceType: ReferenceTypeRelation, 140 ReferenceMarkdown: "relation member", 141 TargetSource: &testSource, 142 TargetPosition: &input.Position{LineNumber: 3, ColumnPosition: 4}, 143 TargetSourceCode: "relation member: user\n", 144 TargetNamePositionOffset: 9, 145 }, 146 }, 147 { 148 name: "filled in type", 149 schema: `definition user {} 150 151 definition resource { 152 relation viewer: user | resource 153 permission view = viewer 154 } 155 `, 156 line: 3, 157 column: 29, 158 expectedReference: &SchemaReference{ 159 Source: input.Source("test"), 160 Position: input.Position{LineNumber: 3, ColumnPosition: 29}, 161 Text: "resource", 162 ReferenceType: ReferenceTypeDefinition, 163 ReferenceMarkdown: "definition resource", 164 TargetSource: &testSource, 165 TargetPosition: &input.Position{LineNumber: 2, ColumnPosition: 3}, 166 TargetSourceCode: "definition resource {\n\t// ...\n}", 167 TargetNamePositionOffset: 11, 168 }, 169 }, 170 { 171 name: "caveat reference", 172 schema: `definition user {} 173 174 caveat somecaveat(someparam int) { 175 someparam < 42 176 } 177 178 definition resource { 179 relation viewer: user with somecaveat 180 permission view = viewer 181 } 182 `, 183 line: 7, 184 column: 35, 185 expectedReference: &SchemaReference{ 186 Source: input.Source("test"), 187 Position: input.Position{LineNumber: 7, ColumnPosition: 35}, 188 Text: "somecaveat", 189 ReferenceType: ReferenceTypeCaveat, 190 ReferenceMarkdown: "caveat somecaveat", 191 TargetSource: &testSource, 192 TargetPosition: &input.Position{LineNumber: 2, ColumnPosition: 3}, 193 TargetSourceCode: "caveat somecaveat(someparam int) {\n\t// ...\n}", 194 TargetNamePositionOffset: 7, 195 }, 196 }, 197 { 198 name: "arrow relation reference", 199 schema: `definition user {} 200 201 definition resource { 202 relation viewer: user 203 permission view = viewer->foo 204 } 205 `, 206 line: 4, 207 column: 23, 208 expectedReference: &SchemaReference{ 209 Source: input.Source("test"), 210 Position: input.Position{LineNumber: 4, ColumnPosition: 23}, 211 Text: "viewer", 212 ReferenceType: ReferenceTypeRelation, 213 ReferenceMarkdown: "relation viewer", 214 TargetSource: &testSource, 215 TargetPosition: &input.Position{LineNumber: 3, ColumnPosition: 4}, 216 TargetSourceCode: "relation viewer: user\n", 217 TargetNamePositionOffset: 9, 218 }, 219 }, 220 { 221 name: "arrow permission reference", 222 schema: `definition user {} 223 224 definition resource { 225 relation viewer: user 226 permission view = viewer->viewer 227 } 228 `, 229 line: 4, 230 column: 31, 231 expectedReference: nil, 232 }, 233 { 234 name: "caveat parameter reference", 235 schema: `definition user {} 236 237 caveat somecaveat(someparam int) { 238 someparam < 42 239 } 240 241 definition resource { 242 relation viewer: user with somecaveat 243 permission view = viewer 244 } 245 `, 246 line: 3, 247 column: 6, 248 expectedReference: &SchemaReference{ 249 Source: input.Source("test"), 250 Position: input.Position{LineNumber: 3, ColumnPosition: 6}, 251 Text: "someparam", 252 ReferenceType: ReferenceTypeCaveatParameter, 253 ReferenceMarkdown: "someparam int", 254 TargetSource: &testSource, 255 TargetSourceCode: "someparam int", 256 TargetNamePositionOffset: 0, 257 }, 258 }, 259 { 260 name: "longer test", 261 schema: `definition user {} 262 263 definition document { 264 relation viewer: user 265 relation editor: user 266 relation third: user 267 permission another = viewer 268 permission view = third + editor + another 269 }`, 270 line: 7, 271 column: 19, 272 expectedReference: &SchemaReference{ 273 Source: input.Source("test"), 274 Position: input.Position{LineNumber: 7, ColumnPosition: 19}, 275 Text: "third", 276 ReferenceType: ReferenceTypeRelation, 277 ReferenceMarkdown: "relation third", 278 TargetSource: &testSource, 279 TargetPosition: &input.Position{LineNumber: 5, ColumnPosition: 1}, 280 TargetSourceCode: "relation third: user\n", 281 TargetNamePositionOffset: 9, 282 }, 283 }, 284 { 285 name: "reference to comment", 286 schema: ` 287 definition user {} 288 289 definition resource { 290 // viewer is some sort of relation 291 relation viewer: user 292 } 293 `, 294 line: 4, 295 column: 10, 296 expectedReference: nil, 297 }, 298 { 299 name: "reference to on commented", 300 schema: ` 301 definition user {} 302 303 definition resource { 304 // viewer is some sort of relation 305 relation viewer: user 306 } 307 `, 308 line: 5, 309 column: 22, 310 expectedReference: &SchemaReference{ 311 Source: "test", 312 Position: input.Position{LineNumber: 5, ColumnPosition: 22}, 313 Text: "user", 314 ReferenceType: 1, 315 ReferenceMarkdown: "definition user", 316 TargetSource: &testSource, 317 TargetPosition: &input.Position{LineNumber: 1, ColumnPosition: 4}, 318 TargetSourceCode: "definition user {}", 319 TargetNamePositionOffset: 11, 320 }, 321 }, 322 { 323 name: "reference to commented", 324 schema: ` 325 definition user {} 326 327 definition resource { 328 // viewer is some sort of relation 329 relation viewer: user 330 } 331 `, 332 line: 5, 333 column: 10, 334 expectedReference: nil, 335 }, 336 { 337 name: "reference to doc comment", 338 schema: ` 339 definition user {} 340 341 /** 342 * This is a comment 343 */ 344 definition resource { 345 relation viewer: user 346 } 347 `, 348 line: 4, 349 column: 5, 350 expectedReference: nil, 351 }, 352 { 353 name: "reference to commented type", 354 schema: ` 355 /** user is a user */ 356 definition user {} 357 358 definition resource { 359 relation viewer: user 360 } 361 `, 362 line: 5, 363 column: 22, 364 expectedReference: &SchemaReference{ 365 Source: "test", 366 Position: input.Position{LineNumber: 5, ColumnPosition: 22}, 367 Text: "user", 368 ReferenceType: 1, 369 ReferenceMarkdown: "definition user", 370 TargetSource: &testSource, 371 TargetPosition: &input.Position{LineNumber: 2, ColumnPosition: 4}, 372 TargetSourceCode: "/** user is a user */\ndefinition user {}", 373 TargetNamePositionOffset: 11, 374 }, 375 }, 376 { 377 name: "reference to commented relation", 378 schema: ` 379 definition user {} 380 381 definition resource { 382 // viewer is a relation for viewing 383 relation viewer: user 384 385 permission view = viewer 386 } 387 `, 388 line: 7, 389 column: 25, 390 expectedReference: &SchemaReference{ 391 Source: "test", 392 Position: input.Position{LineNumber: 7, ColumnPosition: 25}, 393 Text: "viewer", 394 ReferenceType: ReferenceTypeRelation, 395 ReferenceMarkdown: "relation viewer", 396 TargetSource: &testSource, 397 TargetPosition: &input.Position{LineNumber: 5, ColumnPosition: 5}, 398 TargetSourceCode: "// viewer is a relation for viewing\nrelation viewer: user\n", 399 TargetNamePositionOffset: 9, 400 }, 401 }, 402 } 403 404 for _, tc := range tcs { 405 tc := tc 406 t.Run(tc.name, func(t *testing.T) { 407 compiled, err := compiler.Compile(compiler.InputSchema{ 408 Source: input.Source("test"), 409 SchemaString: tc.schema, 410 }, compiler.AllowUnprefixedObjectType()) 411 require.NoError(t, err) 412 413 resolver, err := NewResolver(compiled) 414 require.NoError(t, err) 415 416 ref, err := resolver.ReferenceAtPosition(input.Source("test"), input.Position{ 417 LineNumber: tc.line, 418 ColumnPosition: tc.column, 419 }) 420 421 require.NoError(t, err) 422 require.Equal(t, tc.expectedReference, ref) 423 }) 424 } 425 }