# Copyright (c) Microsoft Corporation. # Licensed under the MIT License. # Empty Collections Loop Test Suite # Tests behavior of various loop types over empty collections # 1. Comprehensions should evaluate to their empty versions # 2. some..in should evaluate to false # 3. every should evaluate to true cases: - note: existential_empty_array description: Existential quantification (some) on empty array should return false example_rego: | # some x in [] # x > 0 # false - no elements to satisfy condition literals: - {} - 0 # comparison value instruction_params: loop_params: - mode: "Any" collection: 0 key_reg: 4 value_reg: 5 body_start: 2 loop_end: 6 result_reg: 6 instructions: - "ArrayNew { dest: 0 }" # Create empty array in register 0 - "LoopStart { params_index: 0 }" - "Load { dest: 7, literal_idx: 1 }" # Load comparison value 0 - "Gt { dest: 8, left: 5, right: 7 }" # Check if current value > 0 - "AssertCondition { condition: 8 }" # Assert the condition - "LoopNext { body_start: 2, loop_end: 6 }" - "Return { value: 6 }" # Return false for empty collection want_result: false - note: universal_empty_array description: Universal quantification (every) on empty array should return true example_rego: | # every x in [] # x > 0 # true - vacuously true (no elements to violate condition) literals: - {} - 0 # comparison value instruction_params: loop_params: - mode: "Every" collection: 0 key_reg: 4 value_reg: 5 result_reg: 6 body_start: 2 loop_end: 6 instructions: - "ArrayNew { dest: 0 }" # Create empty array in register 0 - "LoopStart { params_index: 0 }" - "Load { dest: 7, literal_idx: 1 }" # Load comparison value 0 - "Gt { dest: 8, left: 5, right: 7 }" # Check if current value > 0 - "AssertCondition { condition: 8 }" # Assert the condition - "LoopNext { body_start: 2, loop_end: 6 }" - "Return { value: 6 }" # Return true for empty collection (vacuously true) want_result: true - note: array_comprehension_empty description: Array comprehension on empty collection should return empty array example_rego: | # [x + 1 | x = []; true] # [] # Transform each element by adding 1 literals: - {} - 1 # value to add instruction_params: comprehension_begin_params: - mode: "Array" collection_reg: 1 key_reg: 4 value_reg: 5 body_start: 3 comprehension_end: 9 loop_params: - mode: "ForEach" collection: 0 key_reg: 4 value_reg: 5 result_reg: 8 body_start: 4 loop_end: 9 instructions: - "ArrayNew { dest: 0 }" # Create empty input array in register 0 - "ComprehensionBegin { params_index: 0 }" # Start array comprehension - "LoopStart { params_index: 0 }" # Start loop over array elements - "Load { dest: 6, literal_idx: 1 }" # Load 1 into register 6 - "Add { dest: 7, left: 5, right: 6 }" # Add 1 to current value - "ComprehensionYield { value_reg: 7 }" # Add result to comprehension - "LoadBool { dest: 8, value: true }" # Load true (condition always passes) - "AssertCondition { condition: 8 }" # Assert true condition - "LoopNext { body_start: 4, loop_end: 9 }" # Continue to next iteration or exit - "Return { value: 1 }" # Return the result array (should be empty) want_result: [] - note: set_comprehension_empty description: Set comprehension on empty collection should return empty set example_rego: | # {x + 1 | x = []; true} # set() # Transform each element by adding 1 into a set literals: - {} - 1 # value to add instruction_params: comprehension_begin_params: - mode: "Set" collection_reg: 1 key_reg: 4 value_reg: 5 body_start: 3 comprehension_end: 9 loop_params: - mode: "ForEach" collection: 0 key_reg: 4 value_reg: 5 result_reg: 8 body_start: 4 loop_end: 9 instructions: - "ArrayNew { dest: 0 }" # Create empty input array in register 0 - "ComprehensionBegin { params_index: 0 }" # Start set comprehension - "LoopStart { params_index: 0 }" # Start loop over array elements - "Load { dest: 6, literal_idx: 1 }" # Load 1 into register 6 - "Add { dest: 7, left: 5, right: 6 }" # Add 1 to current value - "ComprehensionYield { value_reg: 7 }" # Add result to comprehension - "LoadBool { dest: 8, value: true }" # Load true (condition always passes) - "AssertCondition { condition: 8 }" # Assert true condition - "LoopNext { body_start: 4, loop_end: 9 }" # Continue to next iteration or exit - "Return { value: 1 }" # Return the result set (should be empty) want_result: set!: [] # Set serializes as empty array - note: object_comprehension_empty description: Object comprehension on empty collection should return empty object example_rego: | # {k: v + 1 | some k, v in {}; true} # {} # Transform each key-value pair literals: - {} - 1 # value to add instruction_params: object_create_params: - dest: 0 template_literal_idx: 0 literal_key_fields: [] fields: [] comprehension_begin_params: - mode: "Object" collection_reg: 1 key_reg: 4 value_reg: 5 body_start: 3 comprehension_end: 9 loop_params: - mode: "ForEach" collection: 0 key_reg: 4 value_reg: 5 result_reg: 8 body_start: 4 loop_end: 9 instructions: - "ObjectCreate { params_index: 0 }" - "ComprehensionBegin { params_index: 0 }" # Start object comprehension - "LoopStart { params_index: 0 }" # Start loop over object elements - "Load { dest: 6, literal_idx: 1 }" # Load 1 into register 6 - "Add { dest: 7, left: 5, right: 6 }" # Add 1 to current value - "ComprehensionYield { value_reg: 7 }" # Add result to comprehension (object comprehension needs special handling) - "LoadBool { dest: 8, value: true }" # Load true (condition always passes) - "AssertCondition { condition: 8 }" # Assert true condition - "LoopNext { body_start: 4, loop_end: 9 }" # Continue to next iteration or exit - "Return { value: 1 }" # Return the result object (should be empty) want_result: {} - note: existential_empty_set description: Existential quantification on empty set should return false example_rego: | # some x in set() # x > 0 # false - no elements in set literals: - {} - 0 # comparison value instruction_params: loop_params: - mode: "Any" collection: 0 key_reg: 4 value_reg: 5 result_reg: 6 body_start: 2 loop_end: 6 instructions: - "SetNew { dest: 0 }" # Create empty set in register 0 - "LoopStart { params_index: 0 }" - "Load { dest: 7, literal_idx: 1 }" # Load comparison value 0 - "Gt { dest: 8, left: 5, right: 7 }" # Check if current value > 0 - "AssertCondition { condition: 8 }" # Assert the condition - "LoopNext { body_start: 2, loop_end: 6 }" - "Return { value: 6 }" # Return false for empty set want_result: false - note: universal_empty_object description: Universal quantification on empty object should return true example_rego: | # every k, v in {} # v > 0 # true - vacuously true (no key-value pairs to violate condition) literals: - {} - 0 # comparison value instruction_params: object_create_params: - dest: 0 template_literal_idx: 0 literal_key_fields: [] fields: [] loop_params: - mode: "Every" collection: 0 key_reg: 4 value_reg: 5 result_reg: 6 body_start: 2 loop_end: 6 instructions: - "ObjectCreate { params_index: 0 }" - "LoopStart { params_index: 0 }" - "Load { dest: 7, literal_idx: 1 }" # Load comparison value 0 - "Gt { dest: 8, left: 5, right: 7 }" # Check if current value > 0 - "AssertCondition { condition: 8 }" # Assert the condition - "LoopNext { body_start: 2, loop_end: 6 }" - "Return { value: 6 }" # Return true for empty object (vacuously true) want_result: true - note: nested_empty_comprehensions description: Nested comprehensions with empty collections example_rego: | # [[y | y = []; true] | x = []; true] # [] # Nested array comprehension where both inner and outer collections are empty literals: [] instruction_params: comprehension_begin_params: - mode: "Array" collection_reg: 0 key_reg: 2 value_reg: 3 body_start: 3 comprehension_end: 16 - mode: "Array" collection_reg: 6 key_reg: 8 value_reg: 9 body_start: 7 comprehension_end: 12 loop_params: - mode: "ForEach" collection: 0 key_reg: 2 value_reg: 3 result_reg: 10 body_start: 4 loop_end: 16 - mode: "ForEach" collection: 6 key_reg: 8 value_reg: 9 result_reg: 11 body_start: 8 loop_end: 12 instructions: - "ArrayNew { dest: 0 }" # Create empty outer array in register 0 - "ArrayNew { dest: 1 }" # Create empty result array in register 1 - "ComprehensionBegin { params_index: 0 }" - "LoopStart { params_index: 0 }" # Start outer loop # Inner array comprehension (for each x in outer empty array) - "ArrayNew { dest: 6 }" # Create empty inner array in register 6 - "ArrayNew { dest: 7 }" # Create result for inner comprehension in register 7 - "ComprehensionBegin { params_index: 1 }" - "LoopStart { params_index: 1 }" # Start inner loop - "ComprehensionYield { value_reg: 9 }" # Push inner value to inner result (never executes) - "LoadBool { dest: 10, value: true }" # Load true - "AssertCondition { condition: 10 }" # Assert true condition for inner loop - "LoopNext { body_start: 8, loop_end: 12 }" # Continue inner loop - "ComprehensionYield { value_reg: 7 }" # Push inner result to outer result - "LoadBool { dest: 11, value: true }" # Load true - "AssertCondition { condition: 11 }" # Assert true condition for outer loop - "LoopNext { body_start: 4, loop_end: 16 }" # Continue outer loop - "Return { value: 1 }" # Return the nested result (should be empty) want_result: []