Skip to content

Commit

Permalink
Add tests using alexandria cairo library (#394)
Browse files Browse the repository at this point in the history
* document todos and implement bytes31

* layout

* Download alexandria lib in CI

* Add alexandria tests

* Add scarb project

* suggestion and fixes

* Build scarb in test target

* Remove dbg print

* Add karatsuba test

* Clean unused imports

* Add more cases

* Add tests using data structures

* Add more tests

* Clippy

* Comment tests that produce invalid mlir

* Avoid searching twice for func

* Pin alexandria version

* Run scarb formatter

* Dont import unused features

* use a different installation method for scarb

* Fix

* Remove unnecessary flag

* Udpate .PHONY

* Remove char

* Use standard installer with flag

* Remove whitespace

* Fix

* Fix target name

* Try solution

* Output scarb version

* pin scarb version

* Build test files in coverage target

* Fix scarb version

* fix

* Fix command duplication

* Use action to install scarb in macos CI

---------

Co-authored-by: Edgar Luque <[email protected]>
  • Loading branch information
fmoletta and edg-l authored Dec 20, 2023
1 parent 24ef1e4 commit afae1f3
Show file tree
Hide file tree
Showing 10 changed files with 242 additions and 12 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ jobs:
uses: dtolnay/[email protected]
with:
components: clippy
- name: Install scarb
uses: software-mansion/setup-scarb@v1
with:
scarb-version: "2.4.0"
- name: Install deps
run: make deps
- name: Run tests
Expand All @@ -156,6 +160,10 @@ jobs:
uses: Swatinem/rust-cache@v2
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov
- name: Install scarb
uses: software-mansion/setup-scarb@v1
with:
scarb-version: "2.4.0"
- name: Install deps
run: make deps
- name: test and generate coverage
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ proptest = "1.2"
tempfile = "3.6"
test-case = "3.2.1"
walkdir = "2"
serde_json = { version = "1.0"}

[build-dependencies]
cc = "1.0"
Expand Down
23 changes: 17 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: usage build book build-dev build-native coverage check test bench bench-ci doc doc-open install clean
.PHONY: usage build book build-dev build-native coverage check test bench bench-ci doc doc-open install clean install-scarb install-scarb-macos build-alexandria

#
# Environment detection.
Expand Down Expand Up @@ -52,13 +52,13 @@ check: check-llvm
cargo fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings

test: check-llvm needs-cairo2
test: check-llvm needs-cairo2 build-alexandria
cargo test --profile optimized-dev --all-targets --all-features

proptest: check-llvm needs-cairo2
cargo test --profile optimized-dev --all-targets --all-features proptest

coverage: check-llvm needs-cairo2
coverage: check-llvm needs-cairo2 build-alexandria
cargo llvm-cov --verbose --profile optimized-dev --all-features --workspace --lcov --output-path lcov.info

doc: check-llvm
Expand All @@ -81,15 +81,15 @@ clean:

deps:
ifeq ($(UNAME), Linux)
deps: build-cairo-2-compiler
deps: build-cairo-2-compiler install-scarb
endif
ifeq ($(UNAME), Darwin)
deps: build-cairo-2-compiler-macos deps-macos
deps: deps-macos
endif
-rm -rf corelib
-ln -s cairo2/corelib corelib

deps-macos: build-cairo-2-compiler-macos
deps-macos: build-cairo-2-compiler-macos install-scarb-macos
-brew install llvm@17 --quiet
@echo "You can execute the env-macos.sh script to setup the needed env variables."

Expand All @@ -116,3 +116,14 @@ cairo-%-macos.tar:

cairo-%.tar:
curl -L -o "$@" "https://github.com/starkware-libs/cairo/releases/download/v$*/release-x86_64-unknown-linux-musl.tar.gz"

SCARB_VERSION = 2.4.0

install-scarb:
curl --proto '=https' --tlsv1.2 -sSf https://docs.swmansion.com/scarb/install.sh| sh -s -- --no-modify-path --version $(SCARB_VERSION)

install-scarb-macos:
curl --proto '=https' --tlsv1.2 -sSf https://docs.swmansion.com/scarb/install.sh| sh -s -- --version $(SCARB_VERSION)

build-alexandria:
cd tests/alexandria; scarb build
58 changes: 58 additions & 0 deletions tests/alexandria.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use crate::common::GAS;
use cairo_lang_runner::SierraCasmRunner;
use cairo_lang_sierra::program::Program;
use common::{compare_outputs, run_native_program, run_vm_program};
use std::{fs::File, io::BufReader};
use test_case::test_case;

mod common;

#[track_caller]
fn compare_inputless_function(function_name: &str) {
// Load file compiled using `scarb build``
let file = File::open("tests/alexandria/target/dev/alexandria.sierra.json").unwrap();
let reader = BufReader::new(file);
let program: Program = serde_json::from_reader(reader).unwrap();
let module_name = "alexandria";
let runner = SierraCasmRunner::new(
program.clone(),
Some(Default::default()),
Default::default(),
)
.unwrap();

let program: (String, Program, SierraCasmRunner) = (module_name.to_string(), program, runner);
let program = &program;

let result_vm = run_vm_program(program, function_name, &[], Some(GAS as usize)).unwrap();

let result_native = run_native_program(program, function_name, &[]);

compare_outputs(
&program.1,
&program.2.find_function(function_name).unwrap().id,
&result_vm,
&result_native,
)
.expect("compare error");
}

// alexandria_math
#[test_case("fib")]
#[test_case("karatsuba" => ignore["System out of memory"])]
#[test_case("armstrong_number")]
#[test_case("aliquot_sum" => ignore["System out of memory"])]
#[test_case("collatz_sequence" => ignore["Result mismatch"])]
#[test_case("extended_euclidean_algorithm")]
// alexandria_data_structures
#[test_case("vec" => ignore["Gas mismatch"])]
#[test_case("stack" => ignore["Gas mismatch"])]
#[test_case("queue")]
#[test_case("bit_array")]
// alexandria_encoding
#[test_case("base64_encode" => ignore["Gas mismatch"])]
#[test_case("reverse_bits" => ignore["Invalid MlIR"])]
#[test_case("reverse_bytes"=> ignore["Invalid MlIR"])]
fn test_cases(function_name: &str) {
compare_inputless_function(function_name)
}
1 change: 1 addition & 0 deletions tests/alexandria/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target
35 changes: 35 additions & 0 deletions tests/alexandria/Scarb.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Code generated by scarb DO NOT EDIT.
version = 1

[[package]]
name = "alexandria"
version = "0.1.0"
dependencies = [
"alexandria_data_structures",
"alexandria_encoding",
"alexandria_math",
]

[[package]]
name = "alexandria_data_structures"
version = "0.1.0"
source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.3.0-rc0#ae1d5149ff601a7ac5b39edc867d33ebd83d7f4f"
dependencies = [
"alexandria_encoding",
]

[[package]]
name = "alexandria_encoding"
version = "0.1.0"
source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.3.0-rc0#ae1d5149ff601a7ac5b39edc867d33ebd83d7f4f"
dependencies = [
"alexandria_math",
]

[[package]]
name = "alexandria_math"
version = "0.2.0"
source = "git+https://github.com/keep-starknet-strange/alexandria.git?tag=cairo-v2.3.0-rc0#ae1d5149ff601a7ac5b39edc867d33ebd83d7f4f"
dependencies = [
"alexandria_data_structures",
]
11 changes: 11 additions & 0 deletions tests/alexandria/Scarb.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "alexandria"
version = "0.1.0"
edition = "2023_10"

# See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html

[dependencies]
alexandria_math = { tag = "cairo-v2.3.0-rc0", git = "https://github.com/keep-starknet-strange/alexandria.git" }
alexandria_data_structures = { tag = "cairo-v2.3.0-rc0", git = "https://github.com/keep-starknet-strange/alexandria.git" }
alexandria_encoding = { tag = "cairo-v2.3.0-rc0", git = "https://github.com/keep-starknet-strange/alexandria.git" }
109 changes: 109 additions & 0 deletions tests/alexandria/src/lib.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
mod alexandria {
// Alexandria Math

fn fib() -> felt252 {
alexandria_math::fibonacci::fib(16, 10, 1)
}

fn karatsuba() -> u128 {
alexandria_math::karatsuba::multiply(3754192357923759273591, 18492875)
}

fn armstrong_number() -> bool {
alexandria_math::armstrong_number::is_armstrong_number(472587892687682)
}

fn aliquot_sum() -> u128 {
alexandria_math::aliquot_sum::aliquot_sum(67472587892687682)
}

fn collatz_sequence() -> Array<u128> {
alexandria_math::collatz_sequence::sequence(4332490568290368)
}

fn extended_euclidean_algorithm() -> (u128, u128, u128) {
alexandria_math::extended_euclidean_algorithm::extended_euclidean_algorithm(
384292543952858, 158915958590
)
}

// Alexandria Data Structures

use alexandria_data_structures::vec::{Felt252Vec, VecTrait};
fn vec() -> (felt252, felt252, felt252) {
let mut vec = VecTrait::<Felt252Vec, felt252>::new();
vec.push(12);
vec.push(99);
vec.set(1, 67);
(vec.at(0), vec.at(1), vec.at(2))
}

use alexandria_data_structures::stack::{Felt252Stack, StackTrait};
fn stack() -> (Option<felt252>, Option<felt252>, Option<felt252>, bool) {
let mut stack = StackTrait::<Felt252Stack, felt252>::new();
stack.push(1);
stack.push(2);
stack.push(17);
let top = stack.peek();
stack.pop();
(top, stack.pop(), stack.pop(), stack.is_empty())
}

use alexandria_data_structures::queue::{Queue, QueueTrait};
fn queue() -> (Option<felt252>, Option<felt252>, Option<felt252>, bool) {
let mut queue = QueueTrait::<felt252>::new();
queue.enqueue(3);
queue.enqueue(31);
queue.enqueue(13);
(queue.dequeue(), queue.dequeue(), queue.dequeue(), queue.is_empty())
}

use alexandria_data_structures::bit_array::{BitArray, BitArrayTrait};
fn bit_array() -> Option<felt252> {
let mut bit_array: BitArray = Default::default();
bit_array.write_word_be(340282366920938463463374607431768211455, 128);
bit_array.pop_front();
bit_array.append_bit(true);
bit_array.append_bit(false);
bit_array.append_bit(true);
bit_array.read_word_le(bit_array.len())
}

// Alexandria Encoding
use alexandria_encoding::base64::{Encoder, Decoder, Base64Encoder, Base64Decoder};
use core::array::ArrayTrait;
fn base64_encode() -> (Array<u8>, Array<u8>) {
let mut input = ArrayTrait::<u8>::new();
input.append('C');
input.append('a');
input.append('i');
input.append('r');
input.append('o');
let encoded = Base64Encoder::encode(input);
let decoded = Base64Decoder::decode(encoded.clone());
(encoded, decoded)
}
// Compiling the following functions generates invalid MLIR, please uncomment once the bug is fixed

// use alexandria_encoding::reversible::{U16ReversibleBits, U32ReversibleBits, U64ReversibleBits, U128ReversibleBits, U256ReversibleBits};
// fn reverse_bits() -> (u16, u32, u64, u128, u256) {
// (
// U16ReversibleBits::reverse_bits(@333),
// U32ReversibleBits::reverse_bits(@3333333),
// U64ReversibleBits::reverse_bits(@3333333333333),
// U128ReversibleBits::reverse_bits(@333333333333333333333),
// U256ReversibleBits::reverse_bits(@33333333333333333333333333),
// )
// }

// use alexandria_encoding::reversible::{U16Reversible, U32Reversible, U64Reversible, U128Reversible, U256Reversible};
// fn reverse_bytes() -> (u16, u32, u64, u128, u256) {
// (
// U16Reversible::reverse_bytes(@333),
// U32Reversible::reverse_bytes(@3333333),
// U64Reversible::reverse_bytes(@3333333333333),
// U128Reversible::reverse_bytes(@333333333333333333333),
// U256Reversible::reverse_bytes(@33333333333333333333333333),
// )
// }
}
7 changes: 1 addition & 6 deletions tests/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,12 +251,7 @@ pub fn run_native_program(
cairo_native::execute(
&engine,
&registry,
&program
.funcs
.iter()
.find(|x| x.id.debug_name.as_deref() == Some(&entry_point))
.expect("Test program entry point not found.")
.id,
entry_point_id,
args,
required_initial_gas,
Some(u64::MAX.into()),
Expand Down

0 comments on commit afae1f3

Please sign in to comment.