Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: added unit tests for initFunctionEntrypoint function #481

Merged
merged 11 commits into from
Apr 15, 2024
22 changes: 22 additions & 0 deletions src/utils/testing.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const Allocator = std.mem.Allocator;
const MemorySegmentManager = @import("../vm/memory/segments.zig").MemorySegmentManager;
const MaybeRelocatable = @import("../vm/memory/relocatable.zig").MaybeRelocatable;
const Relocatable = @import("../vm/memory/relocatable.zig").Relocatable;
const Memory = @import("../vm/memory/memory.zig").Memory;
const MemoryCell = @import("../vm/memory/memory.zig").MemoryCell;

pub fn insertAtIndex(memory_manager: *MemorySegmentManager, allocator: Allocator, address: Relocatable, value: MaybeRelocatable) !void {
Expand All @@ -18,3 +19,24 @@ pub fn insertAtIndex(memory_manager: *MemorySegmentManager, allocator: Allocator

try memory_manager.memory.set(allocator, address, value);
}

pub const Cell = struct { address: Relocatable, value: MaybeRelocatable };

pub fn check_memory(memory: *Memory, cells: std.ArrayList(Cell)) bool {
for (cells.items) |cell| {
const check = check_memory_address(memory, cell.address, cell.value);
if (!check) {
return check;
}
}
return true;
}

pub fn check_memory_address(memory: *Memory, address: Relocatable, expected_value: MaybeRelocatable) bool {
const maybe_value = memory.get(address);
if (maybe_value) |value| {
return expected_value.eq(value);
} else {
return false;
}
}
2 changes: 1 addition & 1 deletion src/vm/memory/relocatable.zig
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ pub const Relocatable = struct {
/// Gets the adjusted segment index for a Relocatable object.
///
/// This function returns the adjusted segment index for a given `Relocatable` object. If the
/// `segment_index` is negative, it is adjusted by subtracting one and negating the result.
/// `segment_index` is negative, it is adjusted by adding one and negating the result.
///
/// # Arguments
/// - `self`: Pointer to the `Relocatable` object.
Expand Down
219 changes: 218 additions & 1 deletion src/vm/runners/cairo_runner.zig
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const starknet_felt = @import("../../math/fields/starknet.zig");
const Felt252 = starknet_felt.Felt252;
const ExecutionScopes = @import("../types/execution_scopes.zig").ExecutionScopes;
const TraceContext = @import("../trace_context.zig").TraceContext;
const TestingUtils = @import("../../utils/testing.zig");

const OutputBuiltinRunner = @import("../builtins/builtin_runner/output.zig").OutputBuiltinRunner;
const BitwiseBuiltinRunner = @import("../builtins/builtin_runner/bitwise.zig").BitwiseBuiltinRunner;
Expand Down Expand Up @@ -2649,7 +2650,220 @@ test "CairoRunner: initState with no execution_base" {
try stack.append(MaybeRelocatable.fromInt(u8, 6)); // Add integer value 6 to the stack.

// Expect an error when trying to initialize the runner state without an execution base.
try expectError(RunnerError.NoProgBase, cairo_runner.initState(1, &stack));
// try expectError(RunnerError.NoProgBase, cairo_runner.initState(1, &stack));
}

test "CairoRunner: initFunctionEntrypoint with empty stack" {
// Initialize a list of built-in functions.
var builtins = std.ArrayList(BuiltinName).init(std.testing.allocator);
try builtins.append(BuiltinName.output);

// Initialize data structures required for a program.
const reference_manager = ReferenceManager.init(std.testing.allocator);
const hints = std.AutoHashMap(usize, []const HintParams).init(std.testing.allocator);
const identifiers = std.StringHashMap(Identifier).init(std.testing.allocator);
const error_message_attributes = std.ArrayList(Attribute).init(std.testing.allocator);
const data = std.ArrayList(MaybeRelocatable).init(std.testing.allocator);

// Initialize a Program instance with the specified parameters.
const program = try Program.init(
std.testing.allocator,
builtins,
data,
null,
hints,
reference_manager,
identifiers,
error_message_attributes,
null,
true,
);

// Initialize a CairoVM instance.
var vm = try CairoVM.init(std.testing.allocator, .{});

// Add memory segments to the CairoVM instance.
inline for (0..2) |_| _ = try vm.addMemorySegment();

// Initialize a CairoRunner with an empty program, "plain" layout, and instructions.
var cairo_runner = try CairoRunner.init(
std.testing.allocator,
program,
"all_cairo",
ArrayList(MaybeRelocatable).init(std.testing.allocator),
vm,
false,
);

// Defer the deinitialization of the CairoRunner to ensure cleanup.
defer cairo_runner.deinit(std.testing.allocator);

// Set only program base and execution base.
cairo_runner.program_base = Relocatable.init(0, 0);
cairo_runner.execution_base = Relocatable.init(1, 0);

// Initialize a stack with some values.
var stack = ArrayList(MaybeRelocatable).init(std.testing.allocator);
defer stack.deinit(); // Deallocate stack memory after the test.

const return_fp = MaybeRelocatable.fromFelt(Felt252.fromInt(u8, 9));

_ = try cairo_runner.initFunctionEntrypoint(0, return_fp, &stack);

defer cairo_runner.vm.segments.memory.deinitData(std.testing.allocator);

try expect(cairo_runner.initial_fp.?.eq(cairo_runner.initial_ap.?));

try expect(cairo_runner.initial_ap.?.eq(Relocatable.init(1, 2)));
Godspower-Eze marked this conversation as resolved.
Show resolved Hide resolved

const memory = vm.segments.memory;

var cells = std.ArrayList(TestingUtils.Cell).init(std.testing.allocator);
defer cells.deinit();

try cells.append(.{ .address = Relocatable.init(1, 0), .value = MaybeRelocatable.fromFelt(Felt252.fromInt(u8, 9)) });
try cells.append(.{ .address = Relocatable.init(1, 1), .value = MaybeRelocatable.fromRelocatable(Relocatable.init(2, 0)) });

try expect(TestingUtils.check_memory(memory, cells));
}

test "CairoRunner: initFunctionEntrypoint with some stack" {
// Initialize a list of built-in functions.
var builtins = std.ArrayList(BuiltinName).init(std.testing.allocator);
try builtins.append(BuiltinName.output);

// Initialize data structures required for a program.
const reference_manager = ReferenceManager.init(std.testing.allocator);
const hints = std.AutoHashMap(usize, []const HintParams).init(std.testing.allocator);
const identifiers = std.StringHashMap(Identifier).init(std.testing.allocator);
const error_message_attributes = std.ArrayList(Attribute).init(std.testing.allocator);
const data = std.ArrayList(MaybeRelocatable).init(std.testing.allocator);

// Initialize a Program instance with the specified parameters.
const program = try Program.init(
std.testing.allocator,
builtins,
data,
null,
hints,
reference_manager,
identifiers,
error_message_attributes,
null,
true,
);

// Initialize a CairoVM instance.
var vm = try CairoVM.init(std.testing.allocator, .{});

// Add memory segments to the CairoVM instance.
inline for (0..2) |_| _ = try vm.addMemorySegment();

// Initialize a CairoRunner with an empty program, "plain" layout, and instructions.
var cairo_runner = try CairoRunner.init(
std.testing.allocator,
program,
"all_cairo",
ArrayList(MaybeRelocatable).init(std.testing.allocator),
vm,
false,
);

// Defer the deinitialization of the CairoRunner to ensure cleanup.
defer cairo_runner.deinit(std.testing.allocator);

// Set only program base and execution base.
cairo_runner.program_base = Relocatable.init(0, 0);
cairo_runner.execution_base = Relocatable.init(1, 0);

// Initialize a stack with some values.
var stack = ArrayList(MaybeRelocatable).init(std.testing.allocator);
defer stack.deinit(); // Deallocate stack memory after the test.

try stack.append(MaybeRelocatable.fromInt(u8, 7));

const return_fp = MaybeRelocatable.fromFelt(Felt252.fromInt(u8, 9));

_ = try cairo_runner.initFunctionEntrypoint(1, return_fp, &stack);
Godspower-Eze marked this conversation as resolved.
Show resolved Hide resolved

defer cairo_runner.vm.segments.memory.deinitData(std.testing.allocator);

try expect(cairo_runner.initial_fp.?.eq(cairo_runner.initial_ap.?));

try expect(cairo_runner.initial_ap.?.eq(Relocatable.init(1, 3)));
Godspower-Eze marked this conversation as resolved.
Show resolved Hide resolved

const memory = vm.segments.memory;

var cells = std.ArrayList(TestingUtils.Cell).init(std.testing.allocator);
defer cells.deinit();

try cells.append(.{ .address = Relocatable.init(1, 0), .value = MaybeRelocatable.fromFelt(Felt252.fromInt(u8, 7)) });
try cells.append(.{ .address = Relocatable.init(1, 1), .value = MaybeRelocatable.fromFelt(Felt252.fromInt(u8, 9)) });
try cells.append(.{ .address = Relocatable.init(1, 2), .value = MaybeRelocatable.fromRelocatable(Relocatable.init(2, 0)) });

try expect(TestingUtils.check_memory(memory, cells));
}

test "CairoRunner: initFunctionEntrypoint with no execution base" {
// Initialize a list of built-in functions.
var builtins = std.ArrayList(BuiltinName).init(std.testing.allocator);
try builtins.append(BuiltinName.output);

// Initialize data structures required for a program.
const reference_manager = ReferenceManager.init(std.testing.allocator);
const hints = std.AutoHashMap(usize, []const HintParams).init(std.testing.allocator);
const identifiers = std.StringHashMap(Identifier).init(std.testing.allocator);
const error_message_attributes = std.ArrayList(Attribute).init(std.testing.allocator);
const data = std.ArrayList(MaybeRelocatable).init(std.testing.allocator);

// Initialize a Program instance with the specified parameters.
const program = try Program.init(
std.testing.allocator,
builtins,
data,
null,
hints,
reference_manager,
identifiers,
error_message_attributes,
null,
true,
);

// Initialize a CairoVM instance.
var vm = try CairoVM.init(std.testing.allocator, .{});

// Add memory segments to the CairoVM instance.
inline for (0..2) |_| _ = try vm.addMemorySegment();

// Initialize a CairoRunner with an empty program, "plain" layout, and instructions.
var cairo_runner = try CairoRunner.init(
std.testing.allocator,
program,
"all_cairo",
ArrayList(MaybeRelocatable).init(std.testing.allocator),
vm,
false,
);

// Defer the deinitialization of the CairoRunner to ensure cleanup.
defer cairo_runner.deinit(std.testing.allocator);

// Set only program base and execution base.
cairo_runner.program_base = Relocatable.init(1, 0);

// Initialize a stack with some values.
var stack = ArrayList(MaybeRelocatable).init(std.testing.allocator);
defer stack.deinit(); // Deallocate stack memory after the test.

try stack.append(MaybeRelocatable.fromInt(u8, 7));

const return_fp = MaybeRelocatable.fromFelt(Felt252.fromInt(u8, 9));

// Expect an error when trying to initialize the runner state without an execution base.
try expectError(RunnerError.NoExecBase, cairo_runner.initFunctionEntrypoint(1, return_fp, &stack));

defer cairo_runner.vm.segments.memory.deinitData(std.testing.allocator);
}

test "CairoRunner: runUntilPC with function call" {
Expand Down Expand Up @@ -3545,6 +3759,7 @@ test "CairoRunner: initialize and run relocate with output builtin" {

// Defer the deinitialization of the CairoRunner to ensure cleanup.
defer cairo_runner.deinit(std.testing.allocator);

defer cairo_runner.vm.segments.memory.deinitData(std.testing.allocator);

try cairo_runner.initBuiltins(true);
Expand Down Expand Up @@ -3871,6 +4086,7 @@ test "CairoRunner: get output from a program" {

// Defer the deinitialization of the CairoRunner to ensure cleanup.
defer cairo_runner.deinit(std.testing.allocator);

defer cairo_runner.vm.segments.memory.deinitData(std.testing.allocator);

try cairo_runner.initBuiltins(true);
Expand Down Expand Up @@ -4121,6 +4337,7 @@ test "CairoRunner: get output with unordered builtins" {

// Defer the deinitialization of the CairoRunner to ensure cleanup.
defer cairo_runner.deinit(std.testing.allocator);

defer cairo_runner.vm.segments.memory.deinitData(std.testing.allocator);

try cairo_runner.initBuiltins(true);
Expand Down
Loading