templates.test_errors

  1import smartpy as sp
  2
  3
  4@sp.module
  5def main():
  6    class Counter(sp.Contract):
  7        def __init__(self):
  8            self.data.x = 0
  9
 10        @sp.entrypoint
 11        def incr(self):
 12            self.data.x += 1
 13            assert self.data.x <= 3
 14
 15        @sp.entrypoint
 16        def set(self, x):
 17            self.data.x = x
 18
 19    class B(sp.Contract):
 20        def __init__(self, counter_address):
 21            self.data.counter_address = counter_address
 22            self.data.last = ""
 23
 24        @sp.entrypoint
 25        def ep(self, last):
 26            c_incr = sp.contract(
 27                sp.unit, self.data.counter_address, entrypoint="incr"
 28            ).unwrap_some()
 29            sp.transfer((), sp.mutez(0), c_incr)
 30            self.data.last = last
 31
 32    class Factory(sp.Contract):
 33        def __init__(self):
 34            self.data.created = None
 35
 36        @sp.entrypoint
 37        def create(self):
 38            self.data.created = sp.Some(
 39                sp.create_contract(Counter, None, sp.mutez(0), sp.record(x=0))
 40            )
 41
 42        @sp.entrypoint
 43        def set(self, x):
 44            created = self.data.created.unwrap_some()
 45            contract = sp.contract(sp.int, created, entrypoint="set")
 46            sp.transfer(x, sp.tez(0), contract.unwrap_some())
 47
 48        @sp.entrypoint
 49        def incr(self):
 50            created = self.data.created.unwrap_some()
 51            contract = sp.contract(sp.unit, created, entrypoint="incr")
 52            sp.transfer((), sp.tez(0), contract.unwrap_some())
 53
 54
 55def run_test(label, f):
 56    try:
 57        f()
 58    except Exception as e:
 59        print(label)
 60        print(e)
 61
 62
 63# Tests
 64@sp.add_test()
 65def test():
 66    s = sp.test_scenario("s1", main)
 67    counter = main.Counter()
 68    s += counter
 69
 70    b = main.B(counter.address)
 71    s += b
 72
 73    # Simple failure, caught:
 74    counter.set(100)
 75    s.verify((counter.data.x == 100) & (b.data.last == ""))
 76    run_test("e1", lambda: counter.incr())
 77    s.verify((counter.data.x == 100) & (b.data.last == ""))
 78
 79    # We can continue after failure:
 80    counter.set(0)
 81    s.verify((counter.data.x == 0) & (b.data.last == ""))
 82    b.ep("A")
 83    s.verify((counter.data.x == 1) & (b.data.last == "A"))
 84
 85    # Failed transactions are rolled back:
 86    b.ep("B")
 87    s.verify((counter.data.x == 2) & (b.data.last == "B"))
 88    b.ep("C")
 89    s.verify((counter.data.x == 3) & (b.data.last == "C"))
 90    run_test("e2", lambda: b.ep("D"))
 91    s.verify((counter.data.x == 3) & (b.data.last == "C"))
 92
 93    # Expected failure:
 94    counter.incr(_valid=False)
 95    s.verify((counter.data.x == 3) & (b.data.last == "C"))
 96
 97    # Expected failure with specified exception:
 98    counter.incr(_valid=False, _exception="Assert failure: self.data.x <= 3")
 99    s.verify((counter.data.x == 3) & (b.data.last == "C"))
100
101    # Expecting a failure that doesn't happen:
102    run_test("e3", lambda: counter.set(0, _valid=False))
103    s.verify((counter.data.x == 3) & (b.data.last == "C"))
104
105    # Expecting a failure with the wrong error message:
106    run_test("e4", lambda: counter.incr(_valid=False, _exception="expected"))
107    s.verify((counter.data.x == 3) & (b.data.last == "C"))
108
109    # Illegal combination of arguments:
110    run_test("e5", lambda: counter.incr(_valid=True, _exception="expected"))
111    s.verify((counter.data.x == 3) & (b.data.last == "C"))
112
113    # Illegal combination of arguments:
114    run_test("e6", lambda: counter.incr(_valid=True, _exception="expected"))
115    s.verify((counter.data.x == 3) & (b.data.last == "C"))
116
117    # Similar behavior with dynamically created contracts
118    factory = main.Factory()
119    s += factory
120    factory.create()
121    b2 = main.B(factory.data.created.unwrap_some())
122    s += b2
123
124    factory.set(100)
125    run_test("f1", lambda: factory.incr())
126
127    # We can continue after failure:
128    factory.set(0)
129    b2.ep("A")
130    s.verify(b2.data.last == "A")
131
132    # Failed transactions are rolled back:
133    b2.ep("B")
134    s.verify(b2.data.last == "B")
135    b2.ep("C")
136    s.verify(b2.data.last == "C")
137    run_test("e2", lambda: b2.ep("D"))
138    s.verify(b2.data.last == "C")
139
140    # Expected failure:
141    factory.incr(_valid=False)
142    s.verify(b2.data.last == "C")
143
144    # Expected failure with specified exception:
145    factory.incr(_valid=False, _exception="Assert failure: self.data.x <= 3")
146    s.verify(b2.data.last == "C")
147
148    # Expecting a failure that doesn't happen:
149    run_test("e3", lambda: factory.set(0, _valid=False))
150    s.verify(b2.data.last == "C")
151
152    # Expecting a failure with the wrong error message:
153    run_test("e4", lambda: factory.incr(_valid=False, _exception="expected"))
154    s.verify(b2.data.last == "C")
def run_test(label, f):
56def run_test(label, f):
57    try:
58        f()
59    except Exception as e:
60        print(label)
61        print(e)