Skip to content

Commit

Permalink
hydrogen
Browse files Browse the repository at this point in the history
  • Loading branch information
ariady-putra committed Jan 8, 2025
0 parents commit 84876c1
Show file tree
Hide file tree
Showing 48 changed files with 18,937 additions and 0 deletions.
18 changes: 18 additions & 0 deletions .github/workflows/continuous-integration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Continuous Integration

on:
push:
branches: ["main"]
pull_request:

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/[email protected]
- uses: aiken-lang/setup-aiken@v1
with:
version: v1.1.9
- run: aiken fmt --check
- run: aiken check -D
- run: aiken build
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
*.tests
*.plutus
*.address
plutus.json
# Aiken compilation artifacts
artifacts/
# Aiken's project working directory
build/
# Aiken's default documentation export
# docs/
169 changes: 169 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
# test_kit

This library contains a set of tools, mainly for testing purposes:

- [`print`](#print) (pretty-print data with label)
- [`collections`](#collections) (contains some `list` and `zip3` functions)
- [`fuzzy`](#fuzzy) (`address`, `assets`, `certificate`, `governance`, and `transaction` fuzzers)
- [`time`](#time) (to `add`/`subtract` intervals and unwrapping finite time, taking its inclusivity into account)
- [`tx`](#tx) (helps mocking and constructing transaction data using the `transaction` builder)

| ℹ️ | Package info | aiken-extra/test_kit | 🧰 |
| --- | --------------- | ---------------------------------------------------------------------------------------- | --- |
| 🔴 | **Version** | **v0.0.1** | 🛠️ |
| 🔴 | **Codename** | **hydrogen** | 💧 |
| 🔴 | **Status** | **alpha** | 🧪 |
| 🟢 | **Depends on** | [**aiken-lang/fuzz v2.1.0**](https://github.com/aiken-lang/fuzz/releases/tag/v2.1.0) ||
| 🟢 | **Depends on** | [**aiken-lang/stdlib v2.2.0**](https://github.com/aiken-lang/stdlib/releases/tag/v2.2.0) ||
| 🟢 | **Tested with** | [**aiken v1.1.9**](https://github.com/aiken-lang/aiken/releases/tag/v1.1.9) ||

<!-- | 🟢 | **Version** | **boron** | ✅ | -->

<!-- | 🔴 | **Codename** | **helium** | 🔥 | -->
<!-- | 🟡 | **Codename** | **lithium** | ☄️ | -->
<!-- | 🟡 | **Codename** | **beryllium** | ☄️ | -->

<!-- | 🟡 | **Status** | **beta** | ⚗️ | -->

## `print`

Pretty-print data with label:

```gleam
use test_kit.{print}
print("Label", data) // fuzz.label(@"Label: cbor.diagnostic(data)")
```

By calling [`fuzz.label`](https://aiken-lang.github.io/fuzz/aiken/fuzz.html#label) internally,
`print` will also work with property testing.

## `collections`

Zip3:

```gleam
use test_kit/collections
collections.zip3(list_a, list_b, list_c) // -> [(a, b, c)..]
collections.unzip3(list_abc) // -> ([a..], [b..], [c..])
```

List `and` & `or`:

```gleam
use test_kit/collections/logic
[..bools] |> logic.all_true // -> True | False
[..bools] |> logic.all_false // -> True | False
[..bools] |> logic.any_true // -> True | False
[..bools] |> logic.any_false // -> True | False
```

## `fuzzy`

Tuple fuzzer:

```gleam
use test_kit/fuzzy
test prop_tuple((a, b) via fuzzy.tuple(fuzzer_a, fuzzer_b)) { .. }
// also available: tuple3 to tuple9
```

Transaction data fuzzers:

```gleam
use test_kit/fuzzy/fuzzer.{ .. }
test prop_address(address via address_fuzzer(FromFuzzed, WithFuzzedDelegation)) { .. } // random addresses
test prop_assets(value via value_fuzzer(min_lovelaces: 2_000_000)) { .. } // ADA and 0-10 tokens; credit goes to Anastasia-Labs
test prop_blake2b_224(blake2b_224_set via blake2b_224_fuzzer(count: 4)) { .. } // generates 4 distinct Blake2b-224 Hashes each run
test prop_blake2b_256(blake2b_256_set via blake2b_256_fuzzer(count: 6)) { .. } // generates 6 distinct Blake2b-256 Hashes each run
test prop_certificate(d_rep via delegate_representative_fuzzer(when_registered: FromFuzzed)) { .. } // Registered | AlwaysAbstain | AlwaysNoConfidence
test prop_governance(constitution via constitution_fuzzer(some_guardrails: Fuzzed)) { .. } // constitutions with either some guardrails script or none
test prop_transaction(inputs via user_inputs_fuzzer()) { .. } // simple (non-script) inputs; credit goes to Anastasia-Labs
// and more
```

## `time`

Interval additions and subtractions:

```gleam
use test_kit/time.{ .. }
interval.after(25200000) |> add_interval(lower_bound: 6 |> Minute, upper_bound: 5 |> Hour) // == interval.after(25200000 + 6 * 60 * 1_000)
interval.before(360000) |> add_interval(lower_bound: 4 |> DS, upper_bound: 3 |> Second) // == interval.before(360000 + 3 * 1_000)
interval.between(4, 5000) |> add_interval(lower_bound: 2 |> MS, upper_bound: 1 |> CS) // == interval.between(4 + 2, 5000 + 1 * 10)
interval.after(25200000) |> sub_interval(lower_bound: 6 |> Minute, upper_bound: 5 |> Hour) // == interval.after(25200000 - 6 * 60 * 1_000)
interval.before(360000) |> sub_interval(lower_bound: 4 |> DS, upper_bound: 3 |> Second) // == interval.before(360000 - 3 * 1_000)
interval.between(4, 5000) |> sub_interval(lower_bound: 2 |> MS, upper_bound: 1 |> CS) // == interval.between(4 - 2, 5000 - 1 * 10)
// also available: IntervalBound, IntervalBoundType, and PosixTime operations
```

Unwrapping finite time:

```gleam
use test_kit/time/unwrap
unwrap.finite_start_of(interval) // -> PosixTime
unwrap.finite_end_of(interval) // -> PosixTime
// inclusivity is taken into account
```

## `tx`

Constructing transaction data:

```gleam
use test_kit/tx.{ .. }
test validate_something() {
..
let tx = transaction.placeholder
|> add_tx_ref_input(tx_ref_in)
|> add_tx_input(tx_in_1)
|> add_tx_input(tx_in_2)
|> add_tx_output(tx_out_1)
|> add_tx_output(tx_out_2)
|> add_signatory("Signer")
..
// assert:
validator.validate.spend(.., .., .., tx)
}
```

Mocking transaction data:

```gleam
use test_kit/tx/mock.{ .. }
mock_address(from_payment: 1, from_stake: 2)
mock_address("A", "B") // Address with both Payment and Staking part
mock_address(True, False) // Address with only Payment part
mock_verification_key_credential(from: 34) // VerificationKey(#"00000000000000000000000000000000000000000000000000000034")
mock_script_credential(from: 567) // Script(#"00000000000000000000000000000000000000000000000000000567")
mock_verification_key_hash(from: 89) // #"00000000000000000000000000000000000000000000000000000089"
mock_script_hash(from: 10) // #"00000000000000000000000000000000000000000000000000000010"
mock_asset(1112, asset_name: "NFT", quantity: 1) // Value(#"00..............................001112", "NFT", 1)
mock_policy_id(1112) // #"00000000000000000000000000000000000000000000000000001112"
mock_output_reference(131415, output_index: 16) // OutputReference(#"00..............................00131415", 16)
mock_transaction_id(131415) // #"0000000000000000000000000000000000000000000000000000000000131415"
mock_blake2b_224(from: 224) // #"00000000000000000000000000000000000000000000000000000224"
mock_blake2b_256(from: 256) // #"0000000000000000000000000000000000000000000000000000000000000256"
mock_hash_from_bytearray(#"af", size: 4) // #"000000af"
mock_hash_from_int(123, size: 3) // #"000123"
mock_hash(1, size: 2) // #"0001"
```
26 changes: 26 additions & 0 deletions aiken.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# This file was generated by Aiken
# You typically do not need to edit this file

[[requirements]]
name = "aiken-lang/stdlib"
version = "v2.2.0"
source = "github"

[[requirements]]
name = "aiken-lang/fuzz"
version = "v2.1.0"
source = "github"

[[packages]]
name = "aiken-lang/stdlib"
version = "v2.2.0"
requirements = []
source = "github"

[[packages]]
name = "aiken-lang/fuzz"
version = "v2.1.0"
requirements = []
source = "github"

[etags]
73 changes: 73 additions & 0 deletions aiken.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/bin/bash
PROJECT=$(pwd | rev | cut -d '/' -f1 | rev)
MAGENTA='\033[1;35m'
WHITE='\033[1;37m'
RESET='\033[0m'

# aiken format
aiken fmt

# aiken check
echo -e "${MAGENTA}Running${RESET} ${WHITE}aiken check${RESET}:"
aiken c 2>&1 | tee ${PROJECT}.tests
echo "" # new line

# aiken build
echo -e "${MAGENTA}Running${RESET} ${WHITE}aiken build${RESET}:"
aiken b $1
echo "" # new line

# aiken blueprint & address
echo -e "${MAGENTA}Running${RESET} ${WHITE}aiken blueprint${RESET} & ${WHITE}aiken address${RESET}:"
aiken blueprint convert > ${PROJECT}.plutus
aiken address > ${PROJECT}.address
echo "" # new line

# aiken docs
if [ $# -eq 0 ]; then
# README.md
GLEAM_CODE=("\`\`\`gleam")
AIKEN_CODE=("\`\`\`aiken")

# README.md - aiken docs: preprocessing - replace ```gleam with ```aiken
README=()
while IFS= read -r LINE; do
if [ "$LINE" == "$GLEAM_CODE" ]; then
README+=("$AIKEN_CODE")
else
README+=("$LINE")
fi
done < README.md
printf "%s\n" "${README[@]}" > README.md

# Running `aiken docs`
echo -e "${MAGENTA}Running${RESET} ${WHITE}aiken docs${RESET}:"
aiken docs

# README.md - aiken docs: postprocessing - replace ```aiken with ```gleam
README=()
while IFS= read -r LINE; do
if [ "$LINE" == "$AIKEN_CODE" ]; then
README+=("$GLEAM_CODE")
else
README+=("$LINE")
fi
done < README.md
printf "%s\n" "${README[@]}" > README.md
fi

# .gitignore
GITIGNORE=()
GITIGNORE+=("*.tests")
GITIGNORE+=("*.plutus")
GITIGNORE+=("*.address")
while IFS= read -r LINE; do
if [ "$LINE" == "docs/" ]; then
GITIGNORE+=("# docs/")
elif [ "$LINE" != "*.tests" ] &&
[ "$LINE" != "*.plutus" ] &&
[ "$LINE" != "*.address" ]; then
GITIGNORE+=("$LINE")
fi
done < .gitignore
printf "%s\n" "${GITIGNORE[@]}" > .gitignore
23 changes: 23 additions & 0 deletions aiken.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name = "aiken-extra/test_kit"
version = "hydrogen-α"
compiler = "v1.1.9"
plutus = "v3"
license = "Apache-2.0"
description = "An Aiken utility library containing various tools, mainly for testing purposes"

[repository]
user = "aiken-extra"
project = "test_kit"
platform = "github"

[[dependencies]]
name = "aiken-lang/stdlib"
version = "v2.2.0"
source = "github"

[[dependencies]]
name = "aiken-lang/fuzz"
version = "v2.1.0"
source = "github"

[config]
51 changes: 51 additions & 0 deletions check.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/bin/bash

# PROJECT=$(pwd | rev | cut -d '/' -f1 | rev)
MAGENTA='\033[1;35m'
WHITE='\033[1;37m'
RESET='\033[0m'

# Get optional arguments
MATCH_TEST=""
ENV="default"
while getopts "m:E:H" opt; do
case $opt in
m)
MATCH_TEST="$OPTARG"
;;
E)
ENV="$OPTARG"
;;
H)
echo -e "${MAGENTA}Usage${RESET}: ${WHITE}$0${RESET} -m <MATCH_TEST> -E <ENV>"
exit 0
;;
*)
;;
esac
done

# Get the Latest Block-time
echo -e "${MAGENTA}Getting${RESET} the latest ${WHITE}block time${RESET}:"
NOW=$(curl "https://api.koios.rest/api/v1/tip?select=block_time" | jq .[].block_time)
echo ""

# Print the Latest Block-time:
echo -e "${MAGENTA}Current${RESET} ${WHITE}block time${RESET}: ${NOW}000"
echo ""

# Configure `aiken.toml`
CONFIG=()
while read LINE; do
if [[ "$LINE" == now* ]]; then
CONFIG+=("now = ${NOW}000")
else
CONFIG+=("$LINE")
fi
done < aiken.toml
printf "%s\n" "${CONFIG[@]}" > aiken.toml

# Run `aiken check``
echo -e "${MAGENTA}Running${RESET} ${WHITE}aiken check${RESET}:"
aiken c -m "${MATCH_TEST}" --env "${ENV}"
echo ""
2 changes: 2 additions & 0 deletions docs/css/atom-one-dark.min.css

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

2 changes: 2 additions & 0 deletions docs/css/atom-one-light.min.css

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

Loading

0 comments on commit 84876c1

Please sign in to comment.