@@ -1216,6 +1216,72 @@ func TestSimplifyWithEmptyContext(t *testing.T) {
12161216 require .NotNil (simplified .GetOperation ())
12171217}
12181218
1219+ func TestSimplifyNotConditional (t * testing.T ) {
1220+ t .Parallel ()
1221+ ctx := context .Background ()
1222+ require := require .New (t )
1223+
1224+ // Create test caveat: count < limit
1225+ env , err := caveats .EnvForVariablesWithDefaultTypeSet (map [string ]caveattypes.VariableType {
1226+ "count" : caveattypes .Default .UIntType ,
1227+ "limit" : caveattypes .Default .UIntType ,
1228+ })
1229+ require .NoError (err )
1230+
1231+ limitCaveat , err := caveats .CompileCaveatWithName (env , "count < limit" , "limit_check" )
1232+ require .NoError (err )
1233+
1234+ serialized , err := limitCaveat .Serialize ()
1235+ require .NoError (err )
1236+
1237+ caveatDef := & core.CaveatDefinition {
1238+ Name : "limit_check" ,
1239+ SerializedExpression : serialized ,
1240+ ParameterTypes : env .EncodedParametersTypes (),
1241+ }
1242+
1243+ // Create datastore with caveat
1244+ ds , err := memdb .NewMemdbDatastore (0 , 0 , memdb .DisableGC )
1245+ require .NoError (err )
1246+
1247+ revision , err := ds .ReadWriteTx (ctx , func (ctx context.Context , tx datastore.ReadWriteTransaction ) error {
1248+ return tx .WriteCaveats (ctx , []* core.CaveatDefinition {caveatDef })
1249+ })
1250+ require .NoError (err )
1251+
1252+ reader := ds .SnapshotReader (revision )
1253+ runner := internalcaveats .NewCaveatRunner (caveattypes .Default .TypeSet )
1254+
1255+ // Create NOT expression: NOT limit_check(limit=10)
1256+ // Base case: when child is conditional (partial), NOT conditional should remain conditional
1257+ notExpr := internalcaveats .Invert (
1258+ & core.CaveatExpression {
1259+ OperationOrCaveat : & core.CaveatExpression_Caveat {
1260+ Caveat : & core.ContextualizedCaveat {
1261+ CaveatName : "limit_check" ,
1262+ Context : mustToStruct (t , map [string ]any {"limit" : uint64 (10 )}),
1263+ },
1264+ },
1265+ },
1266+ )
1267+
1268+ // Test with partial/missing context - child caveat is conditional, so NOT should also be conditional
1269+ // We provide limit but not count, making the child caveat partial
1270+ partialContext := map [string ]any {} // No count provided, only limit is in relationship context
1271+
1272+ simplified , passes , err := SimplifyCaveatExpression (ctx , runner , notExpr , partialContext , reader )
1273+ require .NoError (err )
1274+ require .True (passes , "NOT of conditional caveat should pass conditionally" )
1275+ require .NotNil (simplified , "NOT of conditional caveat should remain as NOT expression" )
1276+
1277+ // Verify the structure: should still be a NOT operation with the child caveat
1278+ require .NotNil (simplified .GetOperation (), "Result should be an operation" )
1279+ require .Equal (core .CaveatOperation_NOT , simplified .GetOperation ().Op , "Should be a NOT operation" )
1280+ require .Len (simplified .GetOperation ().Children , 1 , "NOT should have one child" )
1281+ require .NotNil (simplified .GetOperation ().Children [0 ].GetCaveat (), "Child should be the original caveat" )
1282+ require .Equal ("limit_check" , simplified .GetOperation ().Children [0 ].GetCaveat ().CaveatName )
1283+ }
1284+
12191285func TestSimplifyDeeplyNestedCaveats (t * testing.T ) {
12201286 ctx := context .Background ()
12211287 require := require .New (t )
0 commit comments