Skip to main content

Cairo coverage module

Project description

Cairo coverage

This package allows you to have a small coverage report for your cairo files. For now it's a bit hacky but with cairo 0.10.1 it'll be easier.

How to make it work

To install it run:

pip install .

That's the hacky part and i'll explain later why it's needed. You'll need to go into your python packages folder to modify the cairo_runner.py file. To find it easily run which starknet it should display something like BASE_PATH/bin/starknet. The part that we need is BASE_PATH. You'll need to use your preferred editor and follow the steps. I chose to use nano but feel free to use vim or vs code.

  1. nano BASE_PATH/python3.X/site-packages/starkware/cairo/lang/vm/cairo_runner.py
  2. go to the function initialize_vm on line 254 It should look like this:
def initialize_vm(
        self, hint_locals, static_locals: Optional[Dict[str, Any]] = None, vm_class=VirtualMachine
    ):
        context = RunContext(
            pc=self.initial_pc,
            ap=self.initial_ap,
            fp=self.initial_fp,
            memory=self.memory,
            prime=self.program.prime,
        )

We're now going to modify the default argument for the vm_class so it looks like this:

def initialize_vm(
        self, hint_locals, static_locals: Optional[Dict[str, Any]] = None, vm_class=None
    ):
        if vm_class is None:
            vm_class = VirtualMachine
        context = RunContext(
            pc=self.initial_pc,
            ap=self.initial_ap,
            fp=self.initial_fp,
            memory=self.memory,
            prime=self.program.prime,
        )

To understand why all this is necessary we'll take a look on how the coverage works and how python works.

To run the examples:

poetry run python3 -m pytest examples/ -s -W ignore::DeprecationWarning

How cairo coverage works

The first step to create cairo coverage was to find a way on how to know which instruction has been ran and to save them. The way cairo works is that every time you run some cairo code it creates a VM to execute the code (which is pretty obvious I know) but it implies that every transaction will need a new VM (also obvious). But this is a problem for us because we want to know all the pc (program counter) that have been touched by our tests and we can't just ask the VM at the end of the tests because it's wiped at each new transaction. So we would need to find a way to save what pc has been touched for what file and to map back the pc to a cairo line. In order to do that we'll override the default VM and create our own that has all the functionalities we want. Now to override the default VM we can monkey patch it basically cairo_runner.VirtualMachine = CustomVm. This would replace the cairo_runner VirtualMachine by our own but since it's a default value here

def initialize_vm(
        self, hint_locals, static_locals: Optional[Dict[str, Any]] = None, vm_class=VirtualMachine
    ):

VirtualMachine can't be modified once the script has started because this value is set at python's compile time (yes python is compiled). So in order to prevent this we modify the default value to None so the VirtualMachine class can be patched at runtime.

So now we know how to override the VM now let's understand what the VM is actually doing. The first important thing is to save all the pc touched by the tests across all the files we would need a variable that's shared between all the class instances (spoiler we need to find a hacky way to do it easily). Fortunately for us we can do that

@staticmethod
def covered(val: defaultdict(list) = defaultdict(list)) -> defaultdict(list):
    return val

What's happening there is that if you don't supply a value for val it'll use a defaultdict(list) (it's just a dict that returns a list for all the keys even not initialized). The thing is that this dict will be initialized once and then it'll reuse the same instance (because it's set at compile time) so we can share this value between all the class instances. We can then get all the pc touched during the cairo run and at the end of this run save them in the default dict shared between all the instances. Even though pc are interesting we want the cairo lines. In order to do that we'll use the debug_info of each file to map the pc to the cairo line. Once we have all this all we need to do is format it and print it in the terminal (no shame on the output I had to format everything myself)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cairo-coverage-0.1.0.tar.gz (6.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cairo_coverage-0.1.0-py3-none-any.whl (6.2 kB view details)

Uploaded Python 3

File details

Details for the file cairo-coverage-0.1.0.tar.gz.

File metadata

  • Download URL: cairo-coverage-0.1.0.tar.gz
  • Upload date:
  • Size: 6.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.2.0 CPython/3.9.5 Linux/5.14.0-1052-oem

File hashes

Hashes for cairo-coverage-0.1.0.tar.gz
Algorithm Hash digest
SHA256 d6414ab075acf2786ee79465aba4c81aaaeac8af4571b8c78b8ba30ec95ce2fa
MD5 fa4e38dd38b81b849fb7ccbe5e901241
BLAKE2b-256 0d35400698eee59a7f431b979a9ba6a5b87d0cd91fa05a3c3e0ed5edffe70e2a

See more details on using hashes here.

File details

Details for the file cairo_coverage-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: cairo_coverage-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 6.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.2.0 CPython/3.9.5 Linux/5.14.0-1052-oem

File hashes

Hashes for cairo_coverage-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1258988d53587ac2f8e088b05e80b7fad019386c6ab5db8e936ede1e94dc2ffc
MD5 7ca1ec62d2e3b7608549ca26b24d9e6d
BLAKE2b-256 32ddac45b48c9020c45d2865b971c7a373c4b30a5838becddac2bdddb47fe9b3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page