Skip to content

Commit eaaeb32

Browse files
committed
more tests
1 parent a19ae46 commit eaaeb32

File tree

4 files changed

+222
-22
lines changed

4 files changed

+222
-22
lines changed

Ethereum/Abi.juvix

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -535,10 +535,12 @@ HasEvmSize-UInt32 : HasEvmSize UInt32 := HasEvmSize.evmUInt;
535535

536536
-- TODO abstract over size
537537
--- ByteArray of exactly 32 bytes
538-
type ByteArray32 := ByteArray;
538+
type ByteArray32 := privateMk ByteArray
539539

540-
instance
541-
FixedSize-ByteArray32 : FixedSize ByteArray32 := FixedSize.mk 32;
540+
with
541+
instance
542+
FixedSize-ByteArray32 : FixedSize ByteArray32 := FixedSize.mk 32;
543+
end;
542544

543545
type EvmTuple :=
544546
| nil : EvmTuple
@@ -626,8 +628,7 @@ tupleSplit (l : List EvmSize) : BytesConsumer (List (List Byte)) :=
626628
};
627629
in go [] l;
628630

629-
{--
630-
In order to define ;ToBytes; and ;FromBytes; instances for a
631+
{-- In order to define ;ToBytes; and ;FromBytes; instances for a
631632
tuple, we need to follow some mechanical steps.
632633
This module provides a concrete example. See the comments in the instances
633634
declarations below.
@@ -646,10 +647,10 @@ module TupleUsageExample;
646647
Eq-Example : Eq Example;
647648

648649
{-- To define the ;ToBytes; instance we must create an ;EvmTuple; with the fields
649-
of the record given in order. Then we use the ;ToBytes; instance of the ;EvmTuple;
650-
as shown below.
651-
Note that each of the fields must be an instance of ;ToBytes; and ;HasEvmSize;.
652-
--}
650+
of the record given in order. Then we use the ;ToBytes; instance of the ;EvmTuple;
651+
as shown below.
652+
Note that each of the fields must be an instance of ;ToBytes; and ;HasEvmSize;.
653+
--}
653654
instance
654655
ToBytes-Example : ToBytes Example :=
655656
ToBytes.mk@{
@@ -668,17 +669,17 @@ module TupleUsageExample;
668669
};
669670

670671
{-- To define the ;FromBytes; instance we must follow these steps:
671-
1. call `l <- tupleSplit sizes`, where `sizes` is a list of the ;EvmSize; of
672-
the type of each field.
673-
2. case on `l`. `l` will exactly `n` elements, where `n` is the number
674-
of fields with a type `T` such that `evmSize T` is ;EvmSize.static;
675-
3. For each element `s` of `l`, we call:
676-
`fieldName <- BytesConsumer.local FromBytes.fromBytes s`
677-
4. Then, for each field `f` with a dynamic ;EvmSize;, we call:
678-
`f <- FromBytes.fromBytes`
672+
1. call `l <- tupleSplit sizes`, where `sizes` is a list of the ;EvmSize; of
673+
the type of each field.
674+
2. case on `l`. `l` will exactly `n` elements, where `n` is the number
675+
of fields with a type `T` such that `evmSize T` is ;EvmSize.static;
676+
3. For each element `s` of `l`, we call:
677+
`fieldName <- BytesConsumer.local FromBytes.fromBytes s`
678+
4. Then, for each field `f` with a dynamic ;EvmSize;, we call:
679+
`f <- FromBytes.fromBytes`
679680

680681
For a concrete example, see the code below:
681-
--}
682+
--}
682683
instance
683684
FromBytes-Example : FromBytes Example :=
684685
FromBytes.mk@{

Test/Main.juvix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ import Test.Ethereum.Abi as Ethereum;
66

77
main : IO :=
88
runTestSuite
9-
(testSuite "Applib Tests" [Ethereum.test]);
9+
(TestSuite.group "Applib Tests" [Ethereum.test]);
1010
;

Test/Test/Ethereum/Abi.juvix

Lines changed: 200 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,205 @@ module Test.Ethereum.Abi;
22

33
import Stdlib.Prelude open;
44
import Test.JuvixUnit open;
5+
import Anoma.Primitives.FixedSize open;
6+
import Ethereum.Abi open;
7+
import Applib open;
8+
import Stdlib.Debug.Fail using {failwith} open;
9+
10+
{-- In order to define ;ToBytes; and ;FromBytes; instances for a
11+
tuple, we need to follow some mechanical steps.
12+
This module provides a concrete example. See the comments in the instances
13+
declarations below.
14+
--}
15+
module TupleUsageExample;
16+
type Example : Type :=
17+
mk@{
18+
word : UInt32;
19+
bytearray : ByteArray;
20+
int : Int256;
21+
int32 : Int32;
22+
};
23+
24+
deriving instance
25+
Eq-Example : Eq Example;
26+
27+
{-- To define the ;ToBytes; instance we must create an ;EvmTuple; with the fields
28+
of the record given in order. Then we use the ;ToBytes; instance of the ;EvmTuple;
29+
as shown below.
30+
Note that each of the fields must be an instance of ;ToBytes; and ;HasEvmSize;.
31+
--}
32+
instance
33+
ToBytes-Example : ToBytes Example :=
34+
ToBytes.mk@{
35+
toBytes (e : Example) : BytesBuilder Unit :=
36+
do {
37+
let
38+
tup : EvmTuple :=
39+
Example.word e
40+
::: Example.bytearray e
41+
::: Example.int e
42+
::: Example.int32 e
43+
::: EvmTuple.nil;
44+
in
45+
ToBytes.toBytes tup;
46+
};
47+
};
48+
49+
{-- To define the ;FromBytes; instance we must follow these steps:
50+
1. call `l <- tupleSplit sizes`, where `sizes` is a list of the ;EvmSize; of
51+
the type of each field.
52+
2. case on `l`. `l` will exactly `n` elements, where `n` is the number
53+
of fields with a type `T` such that `evmSize T` is ;EvmSize.static;
54+
3. For each element `s` of `l`, we call:
55+
`fieldName <- BytesConsumer.local FromBytes.fromBytes s`
56+
4. Then, for each field `f` with a dynamic ;EvmSize;, we call:
57+
`f <- FromBytes.fromBytes`
58+
59+
For a concrete example, see the code below:
60+
--}
61+
instance
62+
FromBytes-Example : FromBytes Example :=
63+
FromBytes.mk@{
64+
fromBytes : BytesConsumer Example :=
65+
do {
66+
l <- tupleSplit
67+
[evmSize UInt32; evmSize ByteArray; evmSize Int256; evmSize Int32];
68+
case l of {
69+
| [sword; sint; sint32] :=
70+
do {
71+
-- static
72+
word <- BytesConsumer.local FromBytes.fromBytes sword;
73+
int <- BytesConsumer.local FromBytes.fromBytes sint;
74+
int32 <- BytesConsumer.local FromBytes.fromBytes sint32;
75+
-- dynamic
76+
bytearray <- FromBytes.fromBytes;
77+
pure
78+
Example.mk@{
79+
word;
80+
bytearray;
81+
int;
82+
int32;
83+
};
84+
}
85+
| _ := failwith "FromBytes-Example wrong number of static arguments"
86+
};
87+
};
88+
};
89+
90+
instance
91+
Show-Example : Show Example :=
92+
Show.mk@{
93+
show (e : Example) : String :=
94+
Show.show (Example.word e)
95+
++str ", "
96+
++str Show.show (Example.bytearray e)
97+
++str ", "
98+
++str Show.show (Example.int e)
99+
++str ", "
100+
++str Show.show (Example.int32 e);
101+
};
102+
103+
test : TestSuite :=
104+
let
105+
n : List Byte := [3; 4; 5];
106+
b : ByteArray := ByteArray.mk n;
107+
i : Int256 := Int256.fromInt -88888888888888;
108+
i' : Int32 := Int32.fromInt -2147483647;
109+
example : Example :=
110+
Example.mk@{
111+
word := UInt32.fromNat (sub (pow 256 4) 1);
112+
bytearray := b;
113+
int := i;
114+
int32 := i';
115+
};
116+
encodedExample : ByteArray := toByteArray example;
117+
resDecodedExample : Result BytesConsumer.ConsumerError Example :=
118+
fromByteArray {Example} encodedExample;
119+
in testCase
120+
"decode (encode Tuple) == Tuple"
121+
case resDecodedExample of {
122+
| error err := Assertion.fail "decoding failed"
123+
| ok decodedExample := assertEqual "not equal" decodedExample example
124+
};
125+
end;
126+
127+
assertRoundTrip
128+
{A}
129+
{{Show A}}
130+
{{Eq A}}
131+
{{FromBytes A}}
132+
{{ToBytes A}}
133+
(name : String)
134+
(a : A)
135+
: Assertion :=
136+
let
137+
encoded : ByteArray := toByteArray a;
138+
resDecoded : Result BytesConsumer.ConsumerError A := fromByteArray encoded;
139+
in case resDecoded of
140+
| error err :=
141+
Assertion.fail
142+
("decoding " ++str name ++str " failed:\n" ++str show err)
143+
| ok decoded :=
144+
assertEqual
145+
("\n" ++str show a ++str "\nnot equal to:\n" ++str show decoded)
146+
decoded
147+
a;
148+
149+
-- testCase
150+
-- ("decode (encode " ++str name ++str ") == " ++str name)
151+
152+
module UIntN;
153+
test
154+
(A : Type)
155+
{{Show A}}
156+
{{Eq A}}
157+
{{FixedSize A}}
158+
{{ToBytes A}}
159+
{{FromBytes A}}
160+
{{FromNatural A}}
161+
(name : String)
162+
: TestSuite :=
163+
let
164+
size := byteSize {A};
165+
numBits := 8 * size;
166+
in TestSuite.group
167+
name
168+
[
169+
testCase
170+
"encode(0)"
171+
(assertEqual
172+
"not equal"
173+
(toByteArray (fromNat {A} 0))
174+
(ByteArray.fromList (replicate evmAlign 0)));
175+
testCase
176+
("encode(2 ^ " ++str show numBits ++str ")")
177+
(assertEqual
178+
"not equal"
179+
(toByteArray (fromNat {A} (pow 256 size)))
180+
(ByteArray.fromList (replicate evmAlign 0)));
181+
testCase
182+
("encode(2 ^ " ++str show numBits ++str " - 1)")
183+
(assertEqual
184+
"not equal"
185+
(toByteArray {A} (fromNat (sub (pow 256 size) 1)))
186+
(ByteArray.fromList
187+
(replicate (pad32 size) 0 ++ replicate size 255)));
188+
testCase "decode(encode(0))" (assertRoundTrip {A} "0" 0);
189+
testCase
190+
("decode(encode(2 ^ " ++str show numBits ++str " - 1)")
191+
(assertRoundTrip {A} "0" (fromNat (sub (pow 256 size) 1)));
192+
];
193+
end;
194+
195+
module UInt32;
196+
test : TestSuite := UIntN.test UInt32 "UInt32";
197+
end;
198+
199+
module UInt256;
200+
test : TestSuite := UIntN.test UInt256 "UInt256";
201+
end;
5202

6203
test : TestSuite :=
7-
testSuite "TestPass" [testCase "1 == 1" (assertEqual "1 /= 1" 1 1)];
204+
TestSuite.group
205+
"Abi Encoding"
206+
[TupleUsageExample.test; UInt32.test; UInt256.test];

Test/juvix.lock.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
# Do not edit this file manually.
33

44
version: 2
5-
checksum: 1489253342719ff691fb52fdcd21cd732795aec7522e46dd0bb0e7c43b0f8e6c
5+
checksum: 781d66a93aa76588f06ea0781845331a0a5812dfb54ff5b97e53bb9aef531bdb
66
dependencies:
77
- git:
88
name: anoma_juvix-test
9-
ref: f7b836168ee9df7297e3b5a828dfeb64b9c906e1
9+
ref: c2aad75a84ec95f78e32c11f9ae23eccc1d1ddb3
1010
url: https://github.com/anoma/juvix-test
1111
dependencies:
1212
- git:

0 commit comments

Comments
 (0)