44 "testing"
55
66 "github.com/stretchr/testify/require"
7+
8+ "github.com/authzed/spicedb/pkg/schemadsl/compiler"
9+ "github.com/authzed/spicedb/pkg/schemadsl/input"
710)
811
912func TestCloneSchema_Nil (t * testing.T ) {
@@ -390,18 +393,18 @@ func TestCloneSchema_Mutation(t *testing.T) {
390393 require .NotContains (t , original .definitions , "document" )
391394}
392395
393- func TestCloneSchema_WithFunctionedTuplesetOperation (t * testing.T ) {
394- // Test cloning with FunctionedTuplesetOperation
395- anyOp := & FunctionedTuplesetOperation {
396- tuplesetRelation : "parent" ,
397- function : FunctionTypeAny ,
398- computedRelation : "viewer" ,
396+ func TestCloneSchema_WithFunctionedArrowReference (t * testing.T ) {
397+ // Test cloning with FunctionedArrowReference
398+ anyOp := & FunctionedArrowReference {
399+ left : "parent" ,
400+ function : FunctionTypeAny ,
401+ right : "viewer" ,
399402 }
400403
401- allOp := & FunctionedTuplesetOperation {
402- tuplesetRelation : "group" ,
403- function : FunctionTypeAll ,
404- computedRelation : "member" ,
404+ allOp := & FunctionedArrowReference {
405+ left : "group" ,
406+ function : FunctionTypeAll ,
407+ right : "member" ,
405408 }
406409
407410 // Test with both any() and all() functions in a union
@@ -454,46 +457,46 @@ func TestCloneSchema_WithFunctionedTuplesetOperation(t *testing.T) {
454457 clonedUnion := clonedPerm .operation .(* UnionOperation )
455458 require .Len (t , clonedUnion .children , 3 )
456459
457- // Check FunctionedTuplesetOperation with any()
458- clonedAnyOp := clonedUnion .children [0 ].(* FunctionedTuplesetOperation )
460+ // Check FunctionedArrowReference with any()
461+ clonedAnyOp := clonedUnion .children [0 ].(* FunctionedArrowReference )
459462 require .NotSame (t , anyOp , clonedAnyOp )
460- require .Equal (t , "parent" , clonedAnyOp .tuplesetRelation )
463+ require .Equal (t , "parent" , clonedAnyOp .left )
461464 require .Equal (t , FunctionTypeAny , clonedAnyOp .function )
462- require .Equal (t , "viewer" , clonedAnyOp .computedRelation )
465+ require .Equal (t , "viewer" , clonedAnyOp .right )
463466
464- // Check FunctionedTuplesetOperation with all()
465- clonedAllOp := clonedUnion .children [1 ].(* FunctionedTuplesetOperation )
467+ // Check FunctionedArrowReference with all()
468+ clonedAllOp := clonedUnion .children [1 ].(* FunctionedArrowReference )
466469 require .NotSame (t , allOp , clonedAllOp )
467- require .Equal (t , "group" , clonedAllOp .tuplesetRelation )
470+ require .Equal (t , "group" , clonedAllOp .left )
468471 require .Equal (t , FunctionTypeAll , clonedAllOp .function )
469- require .Equal (t , "member" , clonedAllOp .computedRelation )
472+ require .Equal (t , "member" , clonedAllOp .right )
470473
471474 // Check RelationReference
472475 clonedRelRef := clonedUnion .children [2 ].(* RelationReference )
473476 require .NotSame (t , op .children [2 ], clonedRelRef )
474477 require .Equal (t , "direct_viewer" , clonedRelRef .relationName )
475478}
476479
477- func TestCloneOperation_FunctionedTuplesetOperation (t * testing.T ) {
478- // Test direct cloning of FunctionedTuplesetOperation
480+ func TestCloneOperation_FunctionedArrowReference (t * testing.T ) {
481+ // Test direct cloning of FunctionedArrowReference
479482 tests := []struct {
480483 name string
481- op * FunctionedTuplesetOperation
484+ op * FunctionedArrowReference
482485 }{
483486 {
484487 name : "any function" ,
485- op : & FunctionedTuplesetOperation {
486- tuplesetRelation : "parent" ,
487- function : FunctionTypeAny ,
488- computedRelation : "viewer" ,
488+ op : & FunctionedArrowReference {
489+ left : "parent" ,
490+ function : FunctionTypeAny ,
491+ right : "viewer" ,
489492 },
490493 },
491494 {
492495 name : "all function" ,
493- op : & FunctionedTuplesetOperation {
494- tuplesetRelation : "group" ,
495- function : FunctionTypeAll ,
496- computedRelation : "admin" ,
496+ op : & FunctionedArrowReference {
497+ left : "group" ,
498+ function : FunctionTypeAll ,
499+ right : "admin" ,
497500 },
498501 },
499502 {
@@ -514,38 +517,38 @@ func TestCloneOperation_FunctionedTuplesetOperation(t *testing.T) {
514517 require .NotNil (t , cloned )
515518 require .NotSame (t , tt .op , cloned )
516519
517- clonedOp := cloned .(* FunctionedTuplesetOperation )
518- require .Equal (t , tt .op .tuplesetRelation , clonedOp .tuplesetRelation )
520+ clonedOp := cloned .(* FunctionedArrowReference )
521+ require .Equal (t , tt .op .left , clonedOp .left )
519522 require .Equal (t , tt .op .function , clonedOp .function )
520- require .Equal (t , tt .op .computedRelation , clonedOp .computedRelation )
523+ require .Equal (t , tt .op .right , clonedOp .right )
521524
522525 // Test that mutation doesn't affect original
523- clonedOp .tuplesetRelation = "modified"
524- require .NotEqual (t , tt .op .tuplesetRelation , clonedOp .tuplesetRelation )
526+ clonedOp .left = "modified"
527+ require .NotEqual (t , tt .op .left , clonedOp .left )
525528 })
526529 }
527530}
528531
529532func TestCloneSchema_ComplexOperationWithFunctionedTupleset (t * testing.T ) {
530- // Test a complex nested operation tree that includes FunctionedTuplesetOperation
533+ // Test a complex nested operation tree that includes FunctionedArrowReference
531534 op := & UnionOperation {
532535 children : []Operation {
533536 & RelationReference {relationName : "direct" },
534537 & IntersectionOperation {
535538 children : []Operation {
536- & FunctionedTuplesetOperation {
537- tuplesetRelation : "parent" ,
538- function : FunctionTypeAny ,
539- computedRelation : "viewer" ,
539+ & FunctionedArrowReference {
540+ left : "parent" ,
541+ function : FunctionTypeAny ,
542+ right : "viewer" ,
540543 },
541544 & RelationReference {relationName : "approved" },
542545 },
543546 },
544547 & ExclusionOperation {
545- left : & FunctionedTuplesetOperation {
546- tuplesetRelation : "organization" ,
547- function : FunctionTypeAll ,
548- computedRelation : "member" ,
548+ left : & FunctionedArrowReference {
549+ left : "organization" ,
550+ function : FunctionTypeAll ,
551+ right : "member" ,
549552 },
550553 right : & RelationReference {relationName : "suspended" },
551554 },
@@ -585,19 +588,64 @@ func TestCloneSchema_ComplexOperationWithFunctionedTupleset(t *testing.T) {
585588 require .NotSame (t , op , clonedUnion )
586589 require .Len (t , clonedUnion .children , 3 )
587590
588- // Check intersection with FunctionedTuplesetOperation
591+ // Check intersection with FunctionedArrowReference
589592 clonedIntersection := clonedUnion .children [1 ].(* IntersectionOperation )
590593 require .NotSame (t , op .children [1 ], clonedIntersection )
591- clonedFuncOp1 := clonedIntersection .children [0 ].(* FunctionedTuplesetOperation )
592- require .Equal (t , "parent" , clonedFuncOp1 .tuplesetRelation )
594+ clonedFuncOp1 := clonedIntersection .children [0 ].(* FunctionedArrowReference )
595+ require .Equal (t , "parent" , clonedFuncOp1 .left )
593596 require .Equal (t , FunctionTypeAny , clonedFuncOp1 .function )
594- require .Equal (t , "viewer" , clonedFuncOp1 .computedRelation )
597+ require .Equal (t , "viewer" , clonedFuncOp1 .right )
595598
596- // Check exclusion with FunctionedTuplesetOperation
599+ // Check exclusion with FunctionedArrowReference
597600 clonedExclusion := clonedUnion .children [2 ].(* ExclusionOperation )
598601 require .NotSame (t , op .children [2 ], clonedExclusion )
599- clonedFuncOp2 := clonedExclusion .left .(* FunctionedTuplesetOperation )
600- require .Equal (t , "organization" , clonedFuncOp2 .tuplesetRelation )
602+ clonedFuncOp2 := clonedExclusion .left .(* FunctionedArrowReference )
603+ require .Equal (t , "organization" , clonedFuncOp2 .left )
601604 require .Equal (t , FunctionTypeAll , clonedFuncOp2 .function )
602- require .Equal (t , "member" , clonedFuncOp2 .computedRelation )
605+ require .Equal (t , "member" , clonedFuncOp2 .right )
606+ }
607+
608+ func TestClone_ResolvedFunctionedArrowReference (t * testing.T ) {
609+ // Create a test schema with a functioned arrow
610+ schemaString := `definition document {
611+ relation parent: folder
612+ permission view = parent.any(viewer)
613+ }
614+
615+ definition folder {
616+ relation viewer: user
617+ }
618+
619+ definition user {}`
620+
621+ // Step 1: Compile the schema
622+ compiled , err := compiler .Compile (compiler.InputSchema {
623+ Source : input .Source ("test" ),
624+ SchemaString : schemaString ,
625+ }, compiler .AllowUnprefixedObjectType ())
626+ require .NoError (t , err )
627+
628+ // Step 2: Convert to *Schema
629+ schema , err := BuildSchemaFromCompiledSchema (* compiled )
630+ require .NoError (t , err )
631+ require .NotNil (t , schema )
632+
633+ // Step 3: Resolve the schema
634+ resolved , err := ResolveSchema (schema )
635+ require .NoError (t , err )
636+ require .NotNil (t , resolved )
637+
638+ // Step 4: Clone the resolved schema
639+ cloned := resolved .schema .clone ()
640+ require .NotNil (t , cloned )
641+
642+ // Verify that cloning worked correctly
643+ clonedDef := cloned .definitions ["document" ]
644+ require .NotNil (t , clonedDef )
645+ clonedPerm := clonedDef .permissions ["view" ]
646+ require .NotNil (t , clonedPerm )
647+
648+ // The operation should be a ResolvedFunctionedArrowReference
649+ _ , ok := clonedPerm .operation .(* ResolvedFunctionedArrowReference )
650+ require .True (t , ok , "expected ResolvedFunctionedArrowReference after clone" )
603651}
0 commit comments