test_env.rs 23.2 KB
Newer Older
1
// Copyright 2018-2019 Parity Technologies (UK) Ltd.
2
// This file is part of ink!.
3
//
4
// ink! is free software: you can redistribute it and/or modify
5 6 7 8
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
9
// ink! is distributed in the hope that it will be useful,
10 11 12 13 14
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
15
// along with ink!.  If not, see <http://www.gnu.org/licenses/>.
16

17
use super::*;
18
use crate::{
taskooh's avatar
taskooh committed
19 20 21 22
    env::{
        CallError,
        EnvTypes,
    },
23 24 25 26
    memory::collections::hash_map::{
        Entry,
        HashMap,
    },
27
    storage::Key,
28 29 30 31
};
use core::cell::{
    Cell,
    RefCell,
32
};
33
use scale::{
Hero Bird's avatar
Hero Bird committed
34 35 36
    Decode,
    Encode,
};
Andrew Jones's avatar
Andrew Jones committed
37
use std::marker::PhantomData;
38

39 40
/// A wrapper for the generic bytearray used for data in contract events.
#[derive(Debug, Clone, PartialEq, Eq)]
41
pub struct EventData {
Andrew Jones's avatar
Andrew Jones committed
42
    topics: Vec<Vec<u8>>,
43 44
    data: Vec<u8>,
}
45

46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
/// Raw recorded data of smart contract creates and instantiations.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RawCreateData {
    code_hash: Vec<u8>,
    gas_limit: u64,
    value: Vec<u8>,
    input_data: Vec<u8>,
}

/// Decoded recorded data of smart contract creates and instantiations.
pub struct CreateData<E>
where
    E: EnvTypes,
{
    pub code_hash: E::Hash,
    pub gas_limit: u64,
    pub value: E::Balance,
    pub input_data: Vec<u8>,
}

impl<E> From<RawCreateData> for CreateData<E>
where
    E: EnvTypes,
{
    fn from(raw: RawCreateData) -> Self {
        Self {
            code_hash: Decode::decode(&mut &raw.code_hash[..])
                .expect("encountered invalid encoded code hash"),
            gas_limit: raw.gas_limit,
            value: Decode::decode(&mut &raw.value[..])
                .expect("encountered invalid encoded value"),
            input_data: raw.input_data,
        }
    }
}

82 83
impl EventData {
    /// Returns the uninterpreted bytes of the emitted event.
84 85
    fn data_as_bytes(&self) -> &[u8] {
        self.data.as_slice()
86 87
    }
}
88

taskooh's avatar
taskooh committed
89 90 91 92 93 94 95 96 97 98 99
/// Emulates the data given to remote smart contract call instructions.
pub struct RawCallData {
    pub callee: Vec<u8>,
    pub gas: u64,
    pub value: Vec<u8>,
    pub input_data: Vec<u8>,
}

/// Decoded call data of recorded external calls.
pub struct CallData<E>
where
100
    E: EnvTypes,
taskooh's avatar
taskooh committed
101 102 103 104 105 106 107
{
    pub callee: E::AccountId,
    pub gas: u64,
    pub value: E::Balance,
    pub input_data: Vec<u8>,
}

108 109 110 111 112 113 114
/// An entry in the storage of the test environment.
///
/// # Note
///
/// Additionally to its data it also stores the total
/// number of reads and writes done to this entry.
pub struct StorageEntry {
115 116 117 118 119 120
    /// The actual data that is stored in this storage entry.
    data: Vec<u8>,
    /// The number of reads to this storage entry.
    reads: Cell<u64>,
    /// The number of writes to this storage entry.
    writes: u64,
121 122 123
}

impl StorageEntry {
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
    /// Creates a new storage entry for the given data.
    pub fn new(data: Vec<u8>) -> Self {
        Self {
            data,
            reads: Cell::new(0),
            writes: 0,
        }
    }

    /// Increases the read counter by one.
    fn inc_reads(&self) {
        self.reads.set(self.reads.get() + 1);
    }

    /// Increases the write counter by one.
    fn inc_writes(&mut self) {
        self.writes += 1;
    }

    /// Returns the number of reads for this storage entry.
    pub fn reads(&self) -> u64 {
        self.reads.get()
    }

    /// Returns the number of writes to this storage entry.
    pub fn writes(&self) -> u64 {
        self.writes
    }

    /// Returns the data stored in this storage entry.
    ///
    /// # Note
    ///
    /// Also bumps the read counter.
    pub fn read(&self) -> Vec<u8> {
        self.inc_reads();
        self.data.clone()
    }

    /// Writes the given data to this storage entry.
    ///
    /// # Note
    ///
    /// Also bumps the write counter.
    pub fn write(&mut self, new_data: Vec<u8>) {
        self.inc_writes();
        self.data = new_data;
    }
172 173 174 175
}

/// The data underlying to a test environment.
pub struct TestEnvData {
176 177
    /// The storage entries.
    storage: HashMap<Key, StorageEntry>,
178 179 180 181 182
    /// The address of the contract.
    ///
    /// # Note
    ///
    /// The current address can be adjusted by `TestEnvData::set_address`.
Andrew Jones's avatar
Andrew Jones committed
183
    address: Vec<u8>,
184 185 186 187 188
    /// The balance of the contract.
    ///
    /// # Note
    ///
    /// The current balance can be adjusted by `TestEnvData::set_balance`.
Andrew Jones's avatar
Andrew Jones committed
189
    balance: Vec<u8>,
190 191 192 193 194
    /// The caller address for the next contract invocation.
    ///
    /// # Note
    ///
    /// The current caller can be adjusted by `TestEnvData::set_caller`.
Andrew Jones's avatar
Andrew Jones committed
195
    caller: Vec<u8>,
196 197 198 199 200 201
    /// The input data for the next contract invocation.
    ///
    /// # Note
    ///
    /// The current input can be adjusted by `TestEnvData::set_input`.
    input: Vec<u8>,
202 203 204 205 206
    /// The random seed for the next contract invocation.
    ///
    ///  # Note
    ///
    /// The current random seed can be adjusted by `TestEnvData::set_random_seed`.
Andrew Jones's avatar
Andrew Jones committed
207
    random_seed: Vec<u8>,
208 209 210 211 212
    /// The timestamp for the next contract invocation.
    ///
    /// # Note
    ///
    /// The current timestamp can be adjusted by `TestEnvData::set_now`.
Andrew Jones's avatar
Andrew Jones committed
213
    now: Vec<u8>,
214 215 216 217
    /// The current block number for the next contract invocation.
    ///
    /// # Note
    ///
218 219
    /// The current current block number can be adjusted by `TestEnvData::set_block_number`.
    block_number: Vec<u8>,
220 221 222 223
    /// The total number of reads from the storage.
    total_reads: Cell<u64>,
    /// The total number of writes to the storage.
    total_writes: u64,
224 225
    /// Deposited events of the contract invocation.
    events: Vec<EventData>,
226 227
    /// Calls dispatched to the runtime
    dispatched_calls: Vec<Vec<u8>>,
228
    /// The current gas price.
Andrew Jones's avatar
Andrew Jones committed
229
    gas_price: Vec<u8>,
230
    /// The remaining gas.
Andrew Jones's avatar
Andrew Jones committed
231
    gas_left: Vec<u8>,
232
    /// The total transferred value.
Andrew Jones's avatar
Andrew Jones committed
233
    value_transferred: Vec<u8>,
taskooh's avatar
taskooh committed
234
    /// The recorded external calls.
235
    calls: Vec<RawCallData>,
taskooh's avatar
taskooh committed
236 237
    /// The expected return data of the next external call.
    call_return: Vec<u8>,
238 239
    /// Returned data.
    return_data: Vec<u8>,
240 241 242 243
    /// Recorded smart contract instantiations.
    creates: Vec<RawCreateData>,
    /// The address of the next instantiated smart contract.
    next_create_address: Vec<u8>,
244 245 246
}

impl Default for TestEnvData {
247 248
    fn default() -> Self {
        Self {
Andrew Jones's avatar
Andrew Jones committed
249
            address: Vec::new(),
250
            storage: HashMap::new(),
Andrew Jones's avatar
Andrew Jones committed
251 252
            balance: Vec::new(),
            caller: Vec::new(),
253
            input: Vec::new(),
Andrew Jones's avatar
Andrew Jones committed
254 255
            random_seed: Vec::new(),
            now: Vec::new(),
256
            block_number: Vec::new(),
257 258
            total_reads: Cell::new(0),
            total_writes: 0,
259
            events: Vec::new(),
Andrew Jones's avatar
Andrew Jones committed
260 261 262
            gas_price: Vec::new(),
            gas_left: Vec::new(),
            value_transferred: Vec::new(),
263
            dispatched_calls: Vec::new(),
taskooh's avatar
taskooh committed
264 265
            calls: Vec::new(),
            call_return: Vec::new(),
266
            return_data: Vec::new(),
267 268
            creates: Vec::new(),
            next_create_address: Vec::new(),
269 270
        }
    }
271 272 273
}

impl TestEnvData {
274 275
    /// Resets `self` as if no contract execution happened so far.
    pub fn reset(&mut self) {
Andrew Jones's avatar
Andrew Jones committed
276 277
        self.address.clear();
        self.balance.clear();
278
        self.storage.clear();
Andrew Jones's avatar
Andrew Jones committed
279
        self.caller.clear();
280
        self.input.clear();
Andrew Jones's avatar
Andrew Jones committed
281 282
        self.random_seed.clear();
        self.now.clear();
283
        self.block_number.clear();
284 285
        self.total_reads.set(0);
        self.total_writes = 0;
286
        self.events.clear();
287
        self.dispatched_calls.clear();
taskooh's avatar
taskooh committed
288 289
        self.calls.clear();
        self.call_return.clear();
290
        self.return_data.clear();
291 292
        self.creates.clear();
        self.next_create_address.clear();
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324
    }

    /// Increments the total number of reads from the storage.
    fn inc_total_reads(&self) {
        self.total_reads.set(self.total_reads.get() + 1)
    }

    /// Increments the total number of writes to the storage.
    fn inc_total_writes(&mut self) {
        self.total_writes += 1
    }

    /// Returns the total number of reads from the storage.
    pub fn total_reads(&self) -> u64 {
        self.total_reads.get()
    }

    /// Returns the total number of writes to the storage.
    pub fn total_writes(&self) -> u64 {
        self.total_writes
    }

    /// Returns the number of reads from the entry associated by the given key if any.
    pub fn reads_for(&self, key: Key) -> Option<u64> {
        self.storage.get(&key).map(|loaded| loaded.reads())
    }

    /// Returns the number of writes to the entry associated by the given key if any.
    pub fn writes_for(&self, key: Key) -> Option<u64> {
        self.storage.get(&key).map(|loaded| loaded.writes())
    }

325
    /// Sets the contract address for the next contract invocation.
Andrew Jones's avatar
Andrew Jones committed
326
    pub fn set_address(&mut self, new_address: Vec<u8>) {
327 328 329 330
        self.address = new_address;
    }

    /// Sets the contract balance for the next contract invocation.
Andrew Jones's avatar
Andrew Jones committed
331
    pub fn set_balance(&mut self, new_balance: Vec<u8>) {
332 333 334
        self.balance = new_balance;
    }

335
    /// Sets the caller address for the next contract invocation.
Andrew Jones's avatar
Andrew Jones committed
336
    pub fn set_caller(&mut self, new_caller: Vec<u8>) {
337
        self.caller = new_caller;
338 339 340
    }

    /// Sets the input data for the next contract invocation.
Andrew Jones's avatar
Andrew Jones committed
341 342
    pub fn set_input(&mut self, input_bytes: Vec<u8>) {
        self.input = input_bytes;
343
    }
344

345
    /// Appends new event data to the end of the bytearray.
Andrew Jones's avatar
Andrew Jones committed
346
    pub fn add_event(&mut self, topics: &[Vec<u8>], event_data: &[u8]) {
347 348 349 350
        let new_event = EventData {
            topics: topics.to_vec(),
            data: event_data.to_vec(),
        };
351 352 353
        self.events.push(new_event);
    }

354 355 356 357 358
    /// Appends a dispatched call to the runtime
    pub fn add_dispatched_call(&mut self, call: &[u8]) {
        self.dispatched_calls.push(call.to_vec());
    }

359
    /// Sets the random seed for the next contract invocation.
Andrew Jones's avatar
Andrew Jones committed
360 361
    pub fn set_random_seed(&mut self, random_seed_hash: Vec<u8>) {
        self.random_seed = random_seed_hash.to_vec();
362
    }
363

364
    /// Sets the timestamp for the next contract invocation.
Andrew Jones's avatar
Andrew Jones committed
365
    pub fn set_now(&mut self, timestamp: Vec<u8>) {
366 367 368
        self.now = timestamp;
    }

369
    /// Sets the current block number for the next contract invocation.
370 371
    pub fn set_block_number(&mut self, block_number: Vec<u8>) {
        self.block_number = block_number;
372 373
    }

374
    /// Returns an iterator over all emitted events.
375
    pub fn emitted_events(&self) -> impl DoubleEndedIterator<Item = &[u8]> {
376 377 378
        self.events
            .iter()
            .map(|event_data| event_data.data_as_bytes())
379
    }
380 381 382 383 384

    /// Returns an iterator over all dispatched calls
    pub fn dispatched_calls(&self) -> impl DoubleEndedIterator<Item = &[u8]> {
        self.dispatched_calls.iter().map(Vec::as_slice)
    }
385

taskooh's avatar
taskooh committed
386 387
    /// Records a new external call.
    pub fn add_call(&mut self, callee: &[u8], gas: u64, value: &[u8], input_data: &[u8]) {
388
        let new_call = RawCallData {
taskooh's avatar
taskooh committed
389 390 391 392 393 394 395 396
            callee: callee.to_vec(),
            gas,
            value: value.to_vec(),
            input_data: input_data.to_vec(),
        };
        self.calls.push(new_call);
    }

397 398 399 400 401 402 403 404 405 406
    /// Returns an iterator over all recorded external calls.
    pub fn external_calls(&self) -> impl DoubleEndedIterator<Item = &RawCallData> {
        self.calls.iter()
    }

    /// Set the expected return data of the next external call.
    pub fn set_return_data(&mut self, return_data: &[u8]) {
        self.return_data = return_data.to_vec();
    }

407 408 409 410
    /// Returns the latest returned data.
    pub fn returned_data(&self) -> &[u8] {
        &self.return_data
    }
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437

    /// Records a new smart contract instantiation.
    pub fn add_create(
        &mut self,
        code_hash: &[u8],
        gas_limit: u64,
        value: &[u8],
        input_data: &[u8],
    ) {
        let new_create = RawCreateData {
            code_hash: code_hash.to_vec(),
            gas_limit,
            value: value.to_vec(),
            input_data: input_data.to_vec(),
        };
        self.creates.push(new_create);
    }

    /// Returns an iterator over all recorded smart contract instantiations.
    pub fn creates(&self) -> impl DoubleEndedIterator<Item = &RawCreateData> {
        self.creates.iter()
    }

    /// Sets the address of the next instantiated smart contract.
    pub fn set_next_create_address(&mut self, account_id: &[u8]) {
        self.next_create_address = account_id.to_vec();
    }
438 439 440
}

impl TestEnvData {
Andrew Jones's avatar
Andrew Jones committed
441 442
    pub fn address(&self) -> Vec<u8> {
        self.address.clone()
443 444
    }

Andrew Jones's avatar
Andrew Jones committed
445 446
    pub fn balance(&self) -> Vec<u8> {
        self.balance.clone()
447 448
    }

Andrew Jones's avatar
Andrew Jones committed
449 450
    pub fn caller(&self) -> Vec<u8> {
        self.caller.clone()
451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477
    }

    pub fn store(&mut self, key: Key, value: &[u8]) {
        self.inc_total_writes();
        match self.storage.entry(key) {
            Entry::Occupied(mut occupied) => occupied.get_mut().write(value.to_vec()),
            Entry::Vacant(vacant) => {
                vacant.insert(StorageEntry::new(value.to_vec()));
            }
        }
    }

    pub fn clear(&mut self, key: Key) {
        // Storage clears count as storage write.
        self.inc_total_writes();
        self.storage.remove(&key);
    }

    pub fn load(&self, key: Key) -> Option<Vec<u8>> {
        self.inc_total_reads();
        self.storage.get(&key).map(|loaded| loaded.read())
    }

    pub fn input(&self) -> Vec<u8> {
        self.input.clone()
    }

Andrew Jones's avatar
Andrew Jones committed
478 479
    pub fn random_seed(&self) -> Vec<u8> {
        self.random_seed.clone()
480 481
    }

Andrew Jones's avatar
Andrew Jones committed
482 483
    pub fn now(&self) -> Vec<u8> {
        self.now.clone()
484 485
    }

486 487
    pub fn block_number(&self) -> Vec<u8> {
        self.block_number.clone()
488 489
    }

Andrew Jones's avatar
Andrew Jones committed
490 491
    pub fn gas_price(&self) -> Vec<u8> {
        self.gas_price.clone()
492 493
    }

Andrew Jones's avatar
Andrew Jones committed
494 495
    pub fn gas_left(&self) -> Vec<u8> {
        self.gas_left.clone()
496 497
    }

Andrew Jones's avatar
Andrew Jones committed
498 499
    pub fn value_transferred(&self) -> Vec<u8> {
        self.value_transferred.clone()
500 501
    }

502 503
    pub fn return_data(&mut self, data: &[u8]) {
        self.return_data = data.to_vec();
504
    }
505 506 507 508

    pub fn println(&self, content: &str) {
        println!("{}", content)
    }
509

Andrew Jones's avatar
Andrew Jones committed
510
    pub fn deposit_raw_event(&mut self, topics: &[Vec<u8>], data: &[u8]) {
511
        self.add_event(topics, data);
512
    }
513 514 515 516

    pub fn dispatch_call(&mut self, call: &[u8]) {
        self.add_dispatched_call(call);
    }
taskooh's avatar
taskooh committed
517 518 519 520 521 522 523 524 525 526 527

    pub fn call(
        &mut self,
        callee: &[u8],
        gas: u64,
        value: &[u8],
        input_data: &[u8],
    ) -> Vec<u8> {
        self.add_call(callee, gas, value, input_data);
        self.call_return.clone()
    }
528 529 530 531 532 533 534 535 536 537 538

    pub fn create(
        &mut self,
        code_hash: &[u8],
        gas_limit: u64,
        value: &[u8],
        input_data: &[u8],
    ) -> Vec<u8> {
        self.add_create(code_hash, gas_limit, value, input_data);
        self.next_create_address.clone()
    }
539 540 541
}

thread_local! {
542 543 544
    /// The test environment data.
    ///
    /// This needs to be thread local since tests are run
545
    /// in parallel by default which may lead to data races otherwise.
546 547 548
    pub static TEST_ENV_DATA: RefCell<TestEnvData> = {
        RefCell::new(TestEnvData::default())
    };
549 550 551
}

/// Test environment for testing SRML contract off-chain.
Andrew Jones's avatar
Andrew Jones committed
552
pub struct TestEnv<T> {
Hero Bird's avatar
Hero Bird committed
553
    marker: PhantomData<fn() -> T>,
Andrew Jones's avatar
Andrew Jones committed
554 555 556 557 558 559 560 561 562 563 564
}

macro_rules! impl_env_setters_for_test_env {
    ( $( ($fn_name:ident, $name:ident, $ty:ty) ),* ) => {
        $(
            pub fn $fn_name($name: $ty) {
                TEST_ENV_DATA.with(|test_env| test_env.borrow_mut().$fn_name($name.encode()))
            }
        )*
    }
}
565

Hero Bird's avatar
Hero Bird committed
566 567 568 569
impl<T> TestEnv<T>
where
    T: EnvTypes,
{
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584
    /// Resets the test environment as if no contract execution happened so far.
    pub fn reset() {
        TEST_ENV_DATA.with(|test_env| test_env.borrow_mut().reset())
    }

    /// Returns the number of reads from the entry associated by the given key if any.
    pub fn reads_for(key: Key) -> Option<u64> {
        TEST_ENV_DATA.with(|test_env| test_env.borrow().reads_for(key))
    }

    /// Returns the number of writes to the entry associated by the given key if any.
    pub fn writes_for(key: Key) -> Option<u64> {
        TEST_ENV_DATA.with(|test_env| test_env.borrow().writes_for(key))
    }

585 586 587
    /// Returns the latest returned data.
    pub fn returned_data() -> Vec<u8> {
        TEST_ENV_DATA.with(|test_env| test_env.borrow().returned_data().to_vec())
588 589 590 591
    }

    /// Sets the input data for the next contract invocation.
    pub fn set_input(input_bytes: &[u8]) {
Hero Bird's avatar
Hero Bird committed
592 593
        TEST_ENV_DATA
            .with(|test_env| test_env.borrow_mut().set_input(input_bytes.to_vec()))
594
    }
595

596 597 598 599 600 601
    /// Sets the expected return data for the next external call.
    pub fn set_return_data(expected_return_data: &[u8]) {
        TEST_ENV_DATA
            .with(|test_env| test_env.borrow_mut().set_return_data(expected_return_data))
    }

602 603 604 605 606 607 608 609
    /// Sets the address of the next instantiated smart contract.
    pub fn set_next_create_address(account_id: T::AccountId) {
        TEST_ENV_DATA.with(|test_env| {
            test_env
                .borrow_mut()
                .set_next_create_address(&account_id.encode())
        })
    }
Andrew Jones's avatar
Andrew Jones committed
610 611 612 613 614
    impl_env_setters_for_test_env!(
        (set_address, address, T::AccountId),
        (set_balance, balance, T::Balance),
        (set_caller, caller, T::AccountId),
        (set_random_seed, random_seed, T::Hash),
615
        (set_now, now, T::Moment),
616
        (set_block_number, block_number, T::BlockNumber)
Andrew Jones's avatar
Andrew Jones committed
617
    );
618

619
    /// Returns an iterator over all emitted events.
620
    pub fn emitted_events() -> impl DoubleEndedIterator<Item = Vec<u8>> {
621 622 623 624 625 626
        TEST_ENV_DATA.with(|test_env| {
            test_env
                .borrow()
                .emitted_events()
                .map(|event_bytes| event_bytes.to_vec())
                .collect::<Vec<_>>()
Andrew Jones's avatar
Andrew Jones committed
627
                .into_iter()
628
        })
629
    }
630

631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651
    /// Returns an iterator over all emitted events.
    pub fn external_calls() -> impl DoubleEndedIterator<Item = CallData<T>> {
        TEST_ENV_DATA.with(|test_env| {
            test_env
                .borrow()
                .external_calls()
                .map(|raw_call_data| {
                    CallData {
                        callee: Decode::decode(&mut &raw_call_data.callee[..])
                            .expect("invalid encoded callee"),
                        gas: raw_call_data.gas,
                        value: Decode::decode(&mut &raw_call_data.value[..])
                            .expect("invalid encoded value"),
                        input_data: raw_call_data.input_data.clone(),
                    }
                })
                .collect::<Vec<_>>()
                .into_iter()
        })
    }

652 653 654 655 656 657 658 659 660 661 662 663 664
    /// Returns an iterator over all recorded smart contract instantiations.
    pub fn creates() -> impl DoubleEndedIterator<Item = CreateData<T>> {
        TEST_ENV_DATA.with(|test_env| {
            test_env
                .borrow()
                .creates()
                .cloned()
                .map(Into::into)
                .collect::<Vec<_>>()
                .into_iter()
        })
    }

665 666 667 668 669 670 671 672 673 674 675
    /// Returns an iterator over all dispatched calls.
    pub fn dispatched_calls() -> impl DoubleEndedIterator<Item = T::Call> {
        TEST_ENV_DATA.with(|test_env| {
            test_env
                .borrow()
                .dispatched_calls()
                .map(|call| Decode::decode(&mut &call[..]).expect("Valid encoded Call"))
                .collect::<Vec<_>>()
                .into_iter()
        })
    }
676 677
}

678 679 680 681
macro_rules! impl_env_getters_for_test_env {
    ( $( ($fn_name:ident, $ret_name:ty) ),* ) => {
        $(
            fn $fn_name() -> $ret_name {
Andrew Jones's avatar
Andrew Jones committed
682 683
                TEST_ENV_DATA.with(|test_env| Decode::decode(&mut &test_env.borrow().$fn_name()[..])
                    .expect("environment instances are assumed to be correctly encoded"))
684 685 686 687 688
            }
        )*
    }
}

Andrew Jones's avatar
Andrew Jones committed
689
impl<T> EnvTypes for TestEnv<T>
690
where
Andrew Jones's avatar
Andrew Jones committed
691 692 693 694 695 696
    T: EnvTypes,
{
    type AccountId = <T as EnvTypes>::AccountId;
    type Balance = <T as EnvTypes>::Balance;
    type Hash = <T as EnvTypes>::Hash;
    type Moment = <T as EnvTypes>::Moment;
697
    type BlockNumber = <T as EnvTypes>::BlockNumber;
698
    type Call = <T as EnvTypes>::Call;
Andrew Jones's avatar
Andrew Jones committed
699 700
}

Hero Bird's avatar
Hero Bird committed
701 702 703
impl<T> Env for TestEnv<T>
where
    T: EnvTypes,
704
{
705
    impl_env_getters_for_test_env!(
Andrew Jones's avatar
Andrew Jones committed
706 707 708
        (address, T::AccountId),
        (balance, T::Balance),
        (caller, T::AccountId),
709
        (input, Vec<u8>),
Andrew Jones's avatar
Andrew Jones committed
710 711
        (random_seed, T::Hash),
        (now, T::Moment),
712
        (block_number, T::BlockNumber),
Andrew Jones's avatar
Andrew Jones committed
713 714 715
        (gas_price, T::Balance),
        (gas_left, T::Balance),
        (value_transferred, T::Balance)
716
    );
717

718 719
    fn return_data(data: &[u8]) {
        TEST_ENV_DATA.with(|test_env| test_env.borrow_mut().return_data(data))
720
    }
721 722 723 724

    fn println(content: &str) {
        TEST_ENV_DATA.with(|test_env| test_env.borrow().println(content))
    }
725

Andrew Jones's avatar
Andrew Jones committed
726 727 728 729 730 731
    fn deposit_raw_event(topics: &[T::Hash], data: &[u8]) {
        TEST_ENV_DATA.with(|test_env| {
            let topics = topics.iter().map(Encode::encode).collect::<Vec<_>>();
            test_env.borrow_mut().deposit_raw_event(&topics, data)
        })
    }
732 733 734 735

    fn dispatch_raw_call(data: &[u8]) {
        TEST_ENV_DATA.with(|test_env| test_env.borrow_mut().dispatch_call(data))
    }
taskooh's avatar
taskooh committed
736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758

    fn call_invoke(
        callee: T::AccountId,
        gas: u64,
        value: T::Balance,
        input_data: &[u8],
    ) -> Result<(), CallError> {
        let callee = &(callee.encode())[..];
        let value = &(value.encode())[..];
        let _return_data = TEST_ENV_DATA
            .with(|test_env| test_env.borrow_mut().call(callee, gas, value, input_data));
        Ok(())
    }

    fn call_evaluate<U: Decode>(
        callee: T::AccountId,
        gas: u64,
        value: T::Balance,
        input_data: &[u8],
    ) -> Result<U, CallError> {
        let callee = &(callee.encode())[..];
        let value = &(value.encode())[..];
        TEST_ENV_DATA.with(|test_env| {
759
            Decode::decode(
taskooh's avatar
taskooh committed
760 761 762 763 764
                &mut &(test_env.borrow_mut().call(callee, gas, value, input_data))[..],
            )
            .map_err(|_| CallError)
        })
    }
765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782

    fn create(
        code_hash: T::Hash,
        gas_limit: u64,
        value: T::Balance,
        input_data: &[u8],
    ) -> Result<T::AccountId, CreateError> {
        let code_hash = &(code_hash.encode())[..];
        let value = &(value.encode())[..];
        TEST_ENV_DATA.with(|test_env| {
            Decode::decode(
                &mut &(test_env
                    .borrow_mut()
                    .create(code_hash, gas_limit, value, input_data))[..],
            )
            .map_err(|_| CreateError)
        })
    }
Andrew Jones's avatar
Andrew Jones committed
783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809
}

pub enum TestEnvStorage {}

impl EnvStorage for TestEnvStorage {
    unsafe fn store(key: Key, value: &[u8]) {
        TEST_ENV_DATA.with(|test_env| test_env.borrow_mut().store(key, value))
    }

    unsafe fn clear(key: Key) {
        TEST_ENV_DATA.with(|test_env| test_env.borrow_mut().clear(key))
    }

    unsafe fn load(key: Key) -> Option<Vec<u8>> {
        TEST_ENV_DATA.with(|test_env| test_env.borrow().load(key))
    }
}

impl TestEnvStorage {
    /// Returns the total number of reads from the storage.
    pub fn total_reads() -> u64 {
        TEST_ENV_DATA.with(|test_env| test_env.borrow().total_reads())
    }

    /// Returns the total number of writes to the storage.
    pub fn total_writes() -> u64 {
        TEST_ENV_DATA.with(|test_env| test_env.borrow().total_writes())
810
    }
811
}