From c1d0fbd877e771cacb8fcb2aec99f5a9d6c7be89 Mon Sep 17 00:00:00 2001 From: Matias Romeo Date: Mon, 24 Jul 2017 04:28:33 -0300 Subject: [PATCH] add tests to db module (i64 functions) + tests for print/math modules --- contracts/test_api/test_api.cpp | 54 ++++--- contracts/test_api/test_api.hpp | 78 +++++++++- contracts/test_api/test_db.cpp | 176 ++++++++++++++++++++++ contracts/test_api/test_math.cpp | 30 ++++ contracts/test_api/test_message.cpp | 30 ++-- contracts/test_api/test_message.hpp | 31 ---- contracts/test_api/test_print.cpp | 38 ++++- contracts/test_api/test_print.hpp | 12 -- contracts/test_api/test_types.cpp | 21 ++- contracts/test_api/test_types.hpp | 11 -- tests/api_tests/api_tests.cpp | 226 +++++++++++++++++++++++----- 11 files changed, 554 insertions(+), 153 deletions(-) create mode 100644 contracts/test_api/test_db.cpp create mode 100644 contracts/test_api/test_math.cpp delete mode 100644 contracts/test_api/test_message.hpp delete mode 100644 contracts/test_api/test_print.hpp delete mode 100644 contracts/test_api/test_types.hpp diff --git a/contracts/test_api/test_api.cpp b/contracts/test_api/test_api.cpp index c6111afd6..b12e45f27 100644 --- a/contracts/test_api/test_api.cpp +++ b/contracts/test_api/test_api.cpp @@ -1,8 +1,5 @@ #include "test_api.hpp" -#include "test_types.hpp" -#include "test_message.hpp" - extern "C" { void init() { @@ -10,32 +7,43 @@ extern "C" { } void apply( unsigned long long code, unsigned long long action ) { - + //test_types - WASM_TEST_HANDLER(test_types, 1); - WASM_TEST_HANDLER(test_types, 2); - WASM_TEST_HANDLER(test_types, 3); - WASM_TEST_HANDLER(test_types, 4); - + WASM_TEST_HANDLER(test_types, types_size); + WASM_TEST_HANDLER(test_types, char_to_symbol); + WASM_TEST_HANDLER(test_types, string_to_name); + WASM_TEST_HANDLER(test_types, name_class); + //test_message - WASM_TEST_HANDLER(test_message, 1); - WASM_TEST_HANDLER(test_message, 2); - WASM_TEST_HANDLER(test_message, 3); - WASM_TEST_HANDLER(test_message, 4); - WASM_TEST_HANDLER(test_message, 5); - WASM_TEST_HANDLER(test_message, 6); - WASM_TEST_HANDLER(test_message, 7); - WASM_TEST_HANDLER(test_message, 8); - WASM_TEST_HANDLER(test_message, 9); + WASM_TEST_HANDLER(test_message, read_message); + WASM_TEST_HANDLER(test_message, read_message_to_0); + WASM_TEST_HANDLER(test_message, read_message_to_64k); + WASM_TEST_HANDLER(test_message, require_notice); + WASM_TEST_HANDLER(test_message, require_auth); + WASM_TEST_HANDLER(test_message, assert_false); + WASM_TEST_HANDLER(test_message, assert_true); + WASM_TEST_HANDLER(test_message, now); //test_print - WASM_TEST_HANDLER(test_print, 1); - WASM_TEST_HANDLER(test_print, 2); - WASM_TEST_HANDLER(test_print, 3); - WASM_TEST_HANDLER(test_print, 4); - + WASM_TEST_HANDLER(test_print, test_prints); + WASM_TEST_HANDLER(test_print, test_printi); + WASM_TEST_HANDLER(test_print, test_printi128); + WASM_TEST_HANDLER(test_print, test_printn); //test_math + WASM_TEST_HANDLER(test_math, test_multeq_i128); + WASM_TEST_HANDLER(test_math, test_diveq_i128); + WASM_TEST_HANDLER(test_math, test_diveq_i128_by_0); + + //test db + WASM_TEST_HANDLER(test_db, key_i64_general); + WASM_TEST_HANDLER(test_db, key_i64_remove_all); + WASM_TEST_HANDLER(test_db, key_i64_small_load); + WASM_TEST_HANDLER(test_db, key_i64_small_store); + WASM_TEST_HANDLER(test_db, key_i64_store_scope); + WASM_TEST_HANDLER(test_db, key_i64_remove_scope); + WASM_TEST_HANDLER(test_db, key_i64_not_found); + } } diff --git a/contracts/test_api/test_api.hpp b/contracts/test_api/test_api.hpp index bee04610c..2333616ea 100644 --- a/contracts/test_api/test_api.hpp +++ b/contracts/test_api/test_api.hpp @@ -9,4 +9,80 @@ #define WASM_ASSERT(m, message) if(!(m)) { WASM_TEST_ERROR_MESSAGE=(unsigned int)message; return WASM_TEST_FAIL; } typedef unsigned long long u64; -#define WASM_TEST_HANDLER(C, N) if( C::test_id == (action >> 32) && N == (action & (u64(-1) >> 32)) ) { WASM_TEST_ERROR_CODE = C::test##N(); } \ No newline at end of file +#define WASM_TEST_HANDLER(CLASS, METHOD) \ + if( u32(action>>32) == DJBH(#CLASS) && u32(action) == DJBH(#METHOD) ) { \ + WASM_TEST_ERROR_CODE = CLASS::METHOD(); \ + return; \ + } + +typedef unsigned int u32; +static constexpr u32 DJBH(const char* cp) +{ + u32 hash = 5381; + while (*cp) + hash = 33 * hash ^ (unsigned char) *cp++; + return hash; +} + +#pragma pack(push, 1) +struct dummy_message { + char a; //1 + unsigned long long b; //8 + int c; //4 +}; + +struct u128_msg { + unsigned __int128 values[3]; //16*3 +}; +#pragma pack(pop) + +static_assert( sizeof(dummy_message) == 13 , "unexpected packing" ); +static_assert( sizeof(u128_msg) == 16*3 , "unexpected packing" ); + +struct test_types { + static unsigned int types_size(); + static unsigned int char_to_symbol(); + static unsigned int string_to_name(); + static unsigned int name_class(); +}; + +struct test_print { + static unsigned int test_prints(); + static unsigned int test_printi(); + static unsigned int test_printi128(); + static unsigned int test_printn(); +}; + +#define DUMMY_MESSAGE_DEFAULT_A 0x45 +#define DUMMY_MESSAGE_DEFAULT_B 0xab11cd1244556677 +#define DUMMY_MESSAGE_DEFAULT_C 0x7451ae12 + +struct test_message { + + static unsigned int read_message(); + static unsigned int read_message_to_0(); + static unsigned int read_message_to_64k(); + static unsigned int require_notice(); + static unsigned int require_auth(); + static unsigned int assert_false(); + static unsigned int assert_true(); + static unsigned int now(); + +}; + +struct test_math { + static unsigned int test_multeq_i128(); + static unsigned int test_diveq_i128(); + static unsigned int test_diveq_i128_by_0(); +}; + +struct test_db { + static unsigned int key_i64_general(); + static unsigned int key_i64_remove_all(); + static unsigned int key_i64_small_load(); + static unsigned int key_i64_small_store(); + static unsigned int key_i64_store_scope(); + static unsigned int key_i64_remove_scope(); + static unsigned int key_i64_not_found(); +}; + diff --git a/contracts/test_api/test_db.cpp b/contracts/test_api/test_db.cpp new file mode 100644 index 000000000..23bec2e2b --- /dev/null +++ b/contracts/test_api/test_db.cpp @@ -0,0 +1,176 @@ +#include +#include +#include + +#include "test_api.hpp" + +#pragma pack(push, 1) +struct TestModel +{ + AccountName name; + unsigned char age; + uint64_t phone; +}; + +struct TestModelV2 : TestModel +{ + TestModelV2() : new_field(0) {} + + uint64_t new_field; +}; +#pragma pack(pop) + + + +extern "C" { + void memset(void *vptr, unsigned char val, unsigned int size) { + char *ptr = (char *)vptr; + while(size--) { *(ptr++)=val; } + } +} + +unsigned int test_db::key_i64_general() { + uint32_t res = 0; + + TestModel alice{ N(alice), 20, 4234622}; + TestModel bob { N(bob), 15, 11932435}; + TestModel carol{ N(carol), 30, 545342453}; + TestModel dave { N(dave), 46, 6535354}; + + res = store_i64(currentCode(), N(test_table), &dave, sizeof(TestModel)); + WASM_ASSERT(res != 0, "store dave" ); + + res = store_i64(currentCode(), N(test_table), &carol, sizeof(TestModel)); + WASM_ASSERT(res != 0, "store carol" ); + + res = store_i64(currentCode(), N(test_table), &bob, sizeof(TestModel)); + WASM_ASSERT(res != 0, "store bob" ); + + res = store_i64(currentCode(), N(test_table), &alice, sizeof(TestModel)); + WASM_ASSERT(res != 0, "store alice" ); + + memset(&alice, 0, sizeof(TestModel)); + + WASM_ASSERT(alice.name == 0 && alice.age == 0 && alice.phone == 0, "memset"); + + alice.name = N(alice); + + res = load_i64(currentCode(), currentCode(), N(test_table), &alice, sizeof(TestModel)); + WASM_ASSERT(res == sizeof(TestModel) && alice.age == 20 && alice.phone == 4234622, "alice error 1"); + + alice.age = 21; + alice.phone = 1234; + + res = store_i64(currentCode(), N(test_table), &alice, sizeof(TestModel)); + WASM_ASSERT(res == 0, "store alice 2" ); + + memset(&alice, 0, sizeof(TestModel)); + alice.name = N(alice); + + res = load_i64(currentCode(), currentCode(), N(test_table), &alice, sizeof(TestModel)); + WASM_ASSERT(res == sizeof(TestModel) && alice.age == 21 && alice.phone == 1234, "alice error 2"); + + memset(&bob, 0, sizeof(TestModel)); + bob.name = N(bob); + + memset(&carol, 0, sizeof(TestModel)); + carol.name = N(carol); + + memset(&dave, 0, sizeof(TestModel)); + dave.name = N(dave); + + res = load_i64(currentCode(), currentCode(), N(test_table), &bob, sizeof(TestModel)); + WASM_ASSERT(res == sizeof(TestModel) && bob.age == 15 && bob.phone == 11932435, "bob error 1"); + + res = load_i64(currentCode(), currentCode(), N(test_table), &carol, sizeof(TestModel)); + WASM_ASSERT(res == sizeof(TestModel) && carol.age == 30 && carol.phone == 545342453, "carol error 1"); + + res = load_i64(currentCode(), currentCode(), N(test_table), &dave, sizeof(TestModel)); + WASM_ASSERT(res == sizeof(TestModel) && dave.age == 46 && dave.phone == 6535354, "dave error 1"); + + res = load_i64(currentCode(), N(other_code), N(test_table), &alice, sizeof(TestModel)); + WASM_ASSERT(res == -1, "other_code"); + + res = load_i64(currentCode(), currentCode(), N(other_table), &alice, sizeof(TestModel)); + WASM_ASSERT(res == -1, "other_table"); + + + TestModelV2 alicev2; + alicev2.name = N(alice); + + res = load_i64(currentCode(), currentCode(), N(test_table), &alicev2, sizeof(TestModelV2)); + WASM_ASSERT(res == sizeof(TestModel) && alicev2.age == 21 && alicev2.phone == 1234, "alicev2 load"); + + alicev2.new_field = 66655444; + res = store_i64(currentCode(), N(test_table), &alicev2, sizeof(TestModelV2)); + WASM_ASSERT(res == 0, "store alice 3" ); + + memset(&alicev2, 0, sizeof(TestModelV2)); + alicev2.name = N(alice); + + res = load_i64(currentCode(), currentCode(), N(test_table), &alicev2, sizeof(TestModelV2)); + WASM_ASSERT(res == sizeof(TestModelV2) && alicev2.age == 21 && alicev2.phone == 1234 && alicev2.new_field == 66655444, "alice model v2"); + + return WASM_TEST_PASS; +} + +unsigned int test_db::key_i64_remove_all() { + + uint32_t res = 0; + + res = remove_i64(currentCode(), N(test_table), N(alice)); + WASM_ASSERT(res == 1, "remove alice"); + res = remove_i64(currentCode(), N(test_table), N(bob)); + WASM_ASSERT(res == 1, "remove bob"); + res = remove_i64(currentCode(), N(test_table), N(carol)); + WASM_ASSERT(res == 1, "remove carol"); + res = remove_i64(currentCode(), N(test_table), N(dave)); + WASM_ASSERT(res == 1, "remove dave"); + + + res = remove_i64(currentCode(), N(test_table), N(alice)); + WASM_ASSERT(res == 0, "remove alice 2"); + res = remove_i64(currentCode(), N(test_table), N(bob)); + WASM_ASSERT(res == 0, "remove bob 2"); + res = remove_i64(currentCode(), N(test_table), N(carol)); + WASM_ASSERT(res == 0, "remove carol 2"); + res = remove_i64(currentCode(), N(test_table), N(dave)); + WASM_ASSERT(res == 0, "remove dave 2"); + + return WASM_TEST_PASS; +} + +unsigned int test_db::key_i64_small_load() { + uint64_t dummy = 0; + load_i64(currentCode(), currentCode(), N(just_uint64), &dummy, sizeof(uint64_t)-1); + return WASM_TEST_PASS; +} + +unsigned int test_db::key_i64_small_store() { + uint64_t dummy = 0; + store_i64(currentCode(), N(just_uint64), &dummy, sizeof(uint64_t)-1); + return WASM_TEST_PASS; +} + +unsigned int test_db::key_i64_store_scope() { + uint64_t dummy = 0; + store_i64(currentCode(), N(just_uint64), &dummy, sizeof(uint64_t)); + return WASM_TEST_PASS; +} + +unsigned int test_db::key_i64_remove_scope() { + uint64_t dummy = 0; + store_i64(currentCode(), N(just_uint64), &dummy, sizeof(uint64_t)); + return WASM_TEST_PASS; +} + +unsigned int test_db::key_i64_not_found() { + uint64_t dummy = 1000; + + auto res = load_i64(currentCode(), currentCode(), N(just_uint64), &dummy, sizeof(uint64_t)); + WASM_ASSERT(res == -1, "i64_not_found load"); + + res = remove_i64(currentCode(), N(just_uint64), dummy); + WASM_ASSERT(res == 0, "i64_not_found remove"); + return WASM_TEST_PASS; +} diff --git a/contracts/test_api/test_math.cpp b/contracts/test_api/test_math.cpp new file mode 100644 index 000000000..b51900d38 --- /dev/null +++ b/contracts/test_api/test_math.cpp @@ -0,0 +1,30 @@ +#include +#include +#include + +#include "test_api.hpp" + +unsigned int test_math::test_multeq_i128() { + u128_msg msg; + auto n = readMessage(&msg, sizeof(u128_msg)); + WASM_ASSERT( n == sizeof(u128_msg), "test_multeq_i128 n == sizeof(u128_msg)" ); + multeq_i128(msg.values, msg.values+1); + WASM_ASSERT( msg.values[0] == msg.values[2], "test_multeq_i128 msg.values[0] == msg.values[2]" ); + return WASM_TEST_PASS; +} + +unsigned int test_math::test_diveq_i128() { + u128_msg msg; + auto n = readMessage(&msg, sizeof(u128_msg)); + WASM_ASSERT( n == sizeof(u128_msg), "test_diveq_i128 n == sizeof(u128_msg)" ); + diveq_i128(msg.values, msg.values+1); + WASM_ASSERT( msg.values[0] == msg.values[2], "test_diveq_i128 msg.values[0] == msg.values[2]" ); + return WASM_TEST_PASS; +} + +unsigned int test_math::test_diveq_i128_by_0() { + unsigned __int128 a = 100; + unsigned __int128 b = 0; + diveq_i128(&a, &b); + return WASM_TEST_PASS; +} diff --git a/contracts/test_api/test_message.cpp b/contracts/test_api/test_message.cpp index afa6a0b25..508c7a99f 100644 --- a/contracts/test_api/test_message.cpp +++ b/contracts/test_api/test_message.cpp @@ -1,9 +1,8 @@ #include #include "test_api.hpp" -#include "test_message.hpp" -unsigned int test_message::test1() { +unsigned int test_message::read_message() { char buffer[100]; uint32_t total = 0; @@ -32,49 +31,44 @@ unsigned int test_message::test1() { return WASM_TEST_PASS; } -unsigned int test_message::test2() { - uint32_t total = readMessage((void *)4, (1<<16)-4); - return WASM_TEST_PASS; -} - -unsigned int test_message::test3() { +unsigned int test_message::read_message_to_0() { uint32_t total = readMessage((void *)0, 0x7FFFFFFF); return WASM_TEST_PASS; } -unsigned int test_message::test4() { - uint32_t total = readMessage( (void *)(1<<16), 1); +unsigned int test_message::read_message_to_64k() { + uint32_t total = readMessage( (void *)((1<<16)-1), 0x7FFFFFFF); return WASM_TEST_PASS; } -unsigned int test_message::test5() { +unsigned int test_message::require_notice() { eos::requireNotice( N(acc1) ); eos::requireNotice( N(acc2) ); eos::requireNotice( N(acc1), N(acc2) ); return WASM_TEST_PASS; } -unsigned int test_message::test6() { +unsigned int test_message::require_auth() { eos::requireAuth( N(acc3) ); eos::requireAuth( N(acc4) ); return WASM_TEST_PASS; } -unsigned int test_message::test7() { - assert(false, "test_message::test7"); +unsigned int test_message::assert_false() { + assert(false, "test_message::assert_false"); return WASM_TEST_PASS; } -unsigned int test_message::test8() { - assert(true, "test_message::test8"); +unsigned int test_message::assert_true() { + assert(true, "test_message::assert_true"); return WASM_TEST_PASS; } -unsigned int test_message::test9() { +unsigned int test_message::now() { uint32_t tmp = 0; uint32_t total = readMessage(&tmp, sizeof(uint32_t)); WASM_ASSERT( total == sizeof(uint32_t), "total == sizeof(uint32_t)"); - WASM_ASSERT( tmp == now(), "tmp == now()" ); + WASM_ASSERT( tmp == ::now(), "tmp == now()" ); return WASM_TEST_PASS; } diff --git a/contracts/test_api/test_message.hpp b/contracts/test_api/test_message.hpp deleted file mode 100644 index 592ef2c29..000000000 --- a/contracts/test_api/test_message.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#define DUMMY_MESSAGE_DEFAULT_A 0x45 -#define DUMMY_MESSAGE_DEFAULT_B 0xab11cd1244556677 -#define DUMMY_MESSAGE_DEFAULT_C 0x7451ae12 - -#pragma pack(push, 1) -struct dummy_message { - char a; //1 - unsigned long long b; //8 - int c; //4 -}; -#pragma pack(pop) - -static_assert( sizeof(dummy_message) == 13 , "unexpected packing" ); - -struct test_message { - static const int test_id = 2; - static const int total_tests() { return 9; } - - static unsigned int test1(); - static unsigned int test2(); - static unsigned int test3(); - static unsigned int test4(); - static unsigned int test5(); - static unsigned int test6(); - static unsigned int test7(); - static unsigned int test8(); - static unsigned int test9(); -}; - diff --git a/contracts/test_api/test_print.cpp b/contracts/test_api/test_print.cpp index 8a8259222..04dc9bf59 100644 --- a/contracts/test_api/test_print.cpp +++ b/contracts/test_api/test_print.cpp @@ -1,22 +1,44 @@ -#include +#include #include "test_api.hpp" -#include "test_print.hpp" -unsigned int test_print::test1() { +unsigned int test_print::test_prints() { + prints("ab"); + prints(nullptr); + prints("c\0test_prints"); + prints(0); + prints("efg"); + prints(0); return WASM_TEST_PASS; } -unsigned int test_print::test2() { +unsigned int test_print::test_printi() { + printi(0); + printi(556644); + printi(-1); return WASM_TEST_PASS; } -unsigned int test_print::test3() { +unsigned int test_print::test_printi128() { + uint128_t a(-1); + uint128_t b(0); + uint128_t c(87654323456); + printi128(&a); + printi128(&b); + printi128(&c); return WASM_TEST_PASS; } -unsigned int test_print::test4() { +unsigned int test_print::test_printn() { + printn(N(abcde)); + printn(N(abBde)); + printn(N(1q1q1qAA)); + printn(N()); + printn(N(AAAAAA)); + printn(N(abcdefghijk)); + printn(N(abcdefghijkl)); + printn(N(abcdefghijklm)); + printn(N(abcdefghijklmn)); + printn(N(abcdefghijklmno)); return WASM_TEST_PASS; } - - diff --git a/contracts/test_api/test_print.hpp b/contracts/test_api/test_print.hpp deleted file mode 100644 index 405f642a8..000000000 --- a/contracts/test_api/test_print.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -struct test_print { - static const int test_id = 3; - static const int total_tests() { return 4; } - - static unsigned int test1(); - static unsigned int test2(); - static unsigned int test3(); - static unsigned int test4(); -}; - diff --git a/contracts/test_api/test_types.cpp b/contracts/test_api/test_types.cpp index 546c614e6..cb48e8f26 100644 --- a/contracts/test_api/test_types.cpp +++ b/contracts/test_api/test_types.cpp @@ -1,11 +1,8 @@ -#include +#include #include "test_api.hpp" -#include "test_types.hpp" - -#include -unsigned int test_types::test1() { +unsigned int test_types::types_size() { WASM_ASSERT( sizeof(int64_t) == 8, "int64_t size != 8"); WASM_ASSERT( sizeof(uint64_t) == 8, "uint64_t size != 8"); @@ -23,7 +20,7 @@ unsigned int test_types::test1() { return WASM_TEST_PASS; } -unsigned int test_types::test2() { +unsigned int test_types::char_to_symbol() { WASM_ASSERT( eos::char_to_symbol('a') == 1, "eos::char_to_symbol('a') != 1"); WASM_ASSERT( eos::char_to_symbol('b') == 2, "eos::char_to_symbol('b') != 2"); @@ -65,7 +62,7 @@ unsigned int test_types::test2() { return WASM_TEST_PASS; } -unsigned int test_types::test3() { +unsigned int test_types::string_to_name() { WASM_ASSERT( eos::string_to_name("a") == N(a) , "eos::string_to_name(a)" ); WASM_ASSERT( eos::string_to_name("ba") == N(ba) , "eos::string_to_name(ba)" ); @@ -80,8 +77,8 @@ unsigned int test_types::test3() { WASM_ASSERT( eos::string_to_name("kjihgfedcba") == N(kjihgfedcba) , "eos::string_to_name(kjihgfedcba)" ); WASM_ASSERT( eos::string_to_name("lkjihgfedcba") == N(lkjihgfedcba) , "eos::string_to_name(lkjihgfedcba)" ); WASM_ASSERT( eos::string_to_name("mlkjihgfedcba") == N(mlkjihgfedcba) , "eos::string_to_name(mlkjihgfedcba)" ); - WASM_ASSERT( eos::string_to_name("1mlkjihgfedcba") == N(2mlkjihgfedcba) , "eos::string_to_name(2mlkjihgfedcba)" ); - WASM_ASSERT( eos::string_to_name("55mlkjihgfedcba") == N(14mlkjihgfedcba) , "eos::string_to_name(14mlkjihgfedcba)" ); + WASM_ASSERT( eos::string_to_name("mlkjihgfedcba1") == N(mlkjihgfedcba2) , "eos::string_to_name(mlkjihgfedcba2)" ); + WASM_ASSERT( eos::string_to_name("mlkjihgfedcba55") == N(mlkjihgfedcba14) , "eos::string_to_name(mlkjihgfedcba14)" ); WASM_ASSERT( eos::string_to_name("azAA34") == N(azBB34) , "eos::string_to_name N(azBB34)" ); WASM_ASSERT( eos::string_to_name("AZaz12Bc34") == N(AZaz12Bc34) , "eos::string_to_name AZaz12Bc34" ); @@ -90,12 +87,12 @@ unsigned int test_types::test3() { return WASM_TEST_PASS; } -unsigned int test_types::test4() { +unsigned int test_types::name_class() { WASM_ASSERT ( eos::Name(eos::string_to_name("azAA34")).value == N(azAA34), "eos::Name != N(azAA34)" ); WASM_ASSERT ( eos::Name(eos::string_to_name("AABBCC")).value == 0, "eos::Name != N(0)" ); - WASM_ASSERT ( eos::Name(eos::string_to_name("AA11")).value == N(11)<<(5*2), "eos::Name != N(AA11)" ); - WASM_ASSERT ( eos::Name(eos::string_to_name("11AA")).value == N(11), "eos::Name != N(11AA)" ); + WASM_ASSERT ( eos::Name(eos::string_to_name("AA11")).value == N(AA11), "eos::Name != N(AA11)" ); + WASM_ASSERT ( eos::Name(eos::string_to_name("11AA")).value == N(11), "eos::Name != N(11)" ); WASM_ASSERT ( eos::Name(eos::string_to_name("22BBCCXXAA")).value == N(22), "eos::Name != N(22)" ); WASM_ASSERT ( eos::Name(eos::string_to_name("AAAbbcccdd")) == eos::Name(eos::string_to_name("AAAbbcccdd")), "eos::Name == eos::Name" ); diff --git a/contracts/test_api/test_types.hpp b/contracts/test_api/test_types.hpp deleted file mode 100644 index b01177ce6..000000000 --- a/contracts/test_api/test_types.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -struct test_types { - static const int test_id = 1; - static const int total_tests() { return 4; } - - static unsigned int test1(); - static unsigned int test2(); - static unsigned int test3(); - static unsigned int test4(); -}; diff --git a/tests/api_tests/api_tests.cpp b/tests/api_tests/api_tests.cpp index 6533c30ef..b017f7dac 100644 --- a/tests/api_tests/api_tests.cpp +++ b/tests/api_tests/api_tests.cpp @@ -1,4 +1,14 @@ +#include +#include +#include +#include +#include +#include +#include + #include +#include +#include #include #include @@ -22,14 +32,14 @@ #include #include -#include -#include - FC_REFLECT( dummy_message, (a)(b)(c) ); +FC_REFLECT( u128_msg, (values) ); using namespace eos; using namespace chain; +namespace bio = boost::iostreams; + BOOST_AUTO_TEST_SUITE(api_tests) vector assemble_wast( const std::string& wast ) { @@ -88,10 +98,14 @@ void SetCode( testing_blockchain& chain, AccountName account, const char* wast ) } } FC_LOG_AND_RETHROW( ) } -uint32_t CallFunction( testing_blockchain& chain, const types::Message& msg ) { +uint32_t CallFunction( testing_blockchain& chain, const types::Message& msg, const vector& data, const vector& scope = {N(test_api)}) { eos::chain::SignedTransaction trx; - trx.scope = {msg.code}; + trx.scope = scope; + //msg.data.clear(); + vector& dest = *(vector *)(&msg.data); + std::copy(data.begin(), data.end(), std::back_inserter(dest)); + trx.emplaceMessage(msg); trx.expiration = chain.head_block_time() + 100; @@ -126,25 +140,63 @@ string readFile2(const string &fileName) return string(bytes.data(), fileSize); } -#define TEST_METHOD(C, N) ((uint64_t(C::test_id)<<32) | N) +#define TEST_METHOD(CLASS, METHOD) ( (uint64_t(DJBH(#CLASS))<<32) | uint32_t(DJBH(#METHOD)) ) -#define CALL_TEST_FUNCTION(TYPE, REC, AUTH) CallFunction(chain, Message{"test_api", REC, AUTH, TYPE}) -#define CALL_TEST_FUNCTION2(TYPE, REC, AUTH, DATA) CallFunction(chain, Message{"test_api", REC, AUTH, TYPE, DATA}) +#define CALL_TEST_FUNCTION(TYPE, REC, AUTH, DATA) CallFunction(chain, Message{"test_api", REC, AUTH, TYPE}, DATA) +#define CALL_TEST_FUNCTION_SCOPE(TYPE, REC, AUTH, DATA, SCOPE) CallFunction(chain, Message{"test_api", REC, AUTH, TYPE}, DATA, SCOPE) + +bool is_access_violation(fc::unhandled_exception const & e) { + try { + std::rethrow_exception(e.get_inner_exception()); + } + catch (const Runtime::Exception& e) { + return e.cause == Runtime::Exception::Cause::accessViolation; + } catch (...) { + + } + return false; +} -bool is_access_violation(Runtime::Exception const & e) { return e.cause == Runtime::Exception::Cause::accessViolation; } bool is_tx_missing_recipient(tx_missing_recipient const & e) { return true;} bool is_tx_missing_auth(tx_missing_auth const & e) { return true; } +bool is_tx_missing_scope(tx_missing_scope const& e) { return true; } bool is_assert_exception(fc::assert_exception const & e) { return true; } +std::vector capture; + +struct MySink : public bio::sink +{ + + std::streamsize write(const char* s, std::streamsize n) + { + std::string tmp; + tmp.assign(s, n); + capture.push_back(tmp); + std::cout << "stream : [" << tmp << "]" << std::endl; + return n; + } +}; +uint32_t last_fnc_err = 0; +#define CAPTURE(STREAM, EXEC) \ + {\ + capture.clear(); \ + bio::stream_buffer sb; sb.open(MySink()); \ + std::streambuf *oldbuf = std::STREAM.rdbuf(&sb); \ + last_fnc_err = EXEC; \ + std::STREAM.rdbuf(oldbuf); \ + } + + BOOST_FIXTURE_TEST_CASE(test_all, testing_fixture) { try { auto test_api_wast = readFile2("/home/matu/Documents/Dev/eos/contracts/test_api/test_api.wast"); - std::cout << test_api_wast << std::endl; + //std::cout << test_api_wast << std::endl; Make_Blockchain(chain); chain.produce_blocks(2); Make_Account(chain, test_api); + Make_Account(chain, another); Make_Account(chain, acc1); Make_Account(chain, acc2); Make_Account(chain, acc3); @@ -153,66 +205,166 @@ BOOST_FIXTURE_TEST_CASE(test_all, testing_fixture) //Set test code SetCode(chain, "test_api", test_api_wast.c_str()); + SetCode(chain, "another", test_api_wast.c_str()); //Test types - for(int i=1; i<=test_types::total_tests(); i++) - BOOST_CHECK_MESSAGE( CALL_TEST_FUNCTION( TEST_METHOD(test_types, i), {}, {} ) == WASM_TEST_PASS, "test_types::test"< bytes64k((1<<16)); - // BOOST_CHECK_MESSAGE( CALL_TEST_FUNCTION2( TEST_METHOD(test_message, 2), {}, {}, bytes64k) == WASM_TEST_PASS, "test_message::test2()" ); + std::vector raw_bytes((1<<16)); + BOOST_CHECK_MESSAGE( CALL_TEST_FUNCTION( TEST_METHOD(test_message, read_message_to_0), {}, {}, raw_bytes) == WASM_TEST_PASS, "test_message::read_message_to_0()" ); - // BOOST_CHECK_EXCEPTION( CALL_TEST_FUNCTION2( TEST_METHOD(test_message, 3), {}, {}, bytes64k), - // Runtime::Exception, is_access_violation ); + raw_bytes.resize((1<<16)+1); + BOOST_CHECK_EXCEPTION( CALL_TEST_FUNCTION( TEST_METHOD(test_message, read_message_to_0), {}, {}, raw_bytes), + fc::unhandled_exception, is_access_violation ); - // BOOST_CHECK_EXCEPTION( CALL_TEST_FUNCTION2( TEST_METHOD(test_message, 4), {}, {}, bytes64k), - // Runtime::Exception, is_access_violation ); + raw_bytes.resize(1); + BOOST_CHECK_MESSAGE( CALL_TEST_FUNCTION( TEST_METHOD(test_message, read_message_to_64k), {}, {}, raw_bytes) == WASM_TEST_PASS, "test_message::read_message_to_64k()" ); - BOOST_CHECK_EXCEPTION( CALL_TEST_FUNCTION( TEST_METHOD(test_message, 5), {}, {}), + raw_bytes.resize(2); + BOOST_CHECK_EXCEPTION( CALL_TEST_FUNCTION( TEST_METHOD(test_message, read_message_to_64k), {}, {}, raw_bytes), + fc::unhandled_exception, is_access_violation ); + + BOOST_CHECK_EXCEPTION( CALL_TEST_FUNCTION( TEST_METHOD(test_message, require_notice), {}, {}, {}), tx_missing_recipient, is_tx_missing_recipient ); - BOOST_CHECK_EXCEPTION( CALL_TEST_FUNCTION( TEST_METHOD(test_message, 5), sort_names({"acc1"}), {}), + BOOST_CHECK_EXCEPTION( CALL_TEST_FUNCTION( TEST_METHOD(test_message, require_notice), sort_names({"acc1"}), {}, {}), tx_missing_recipient, is_tx_missing_recipient ); - - BOOST_CHECK_EXCEPTION( CALL_TEST_FUNCTION( TEST_METHOD(test_message, 5), sort_names({"acc2"}), {}), + + BOOST_CHECK_EXCEPTION( CALL_TEST_FUNCTION( TEST_METHOD(test_message, require_notice), sort_names({"acc2"}), {}, {}), tx_missing_recipient, is_tx_missing_recipient ); - BOOST_CHECK_MESSAGE( CALL_TEST_FUNCTION( TEST_METHOD(test_message, 5), sort_names({"acc1","acc2"}), {}) == WASM_TEST_PASS, "test_message::test5()"); - - + BOOST_CHECK_MESSAGE( CALL_TEST_FUNCTION( TEST_METHOD(test_message, require_notice), sort_names({"acc1","acc2"}), {}, {}) == WASM_TEST_PASS, "test_message::require_notice()"); - BOOST_CHECK_EXCEPTION( CALL_TEST_FUNCTION( TEST_METHOD(test_message, 6), {}, {}), + BOOST_CHECK_EXCEPTION( CALL_TEST_FUNCTION( TEST_METHOD(test_message, require_auth), {}, {}, {}), tx_missing_auth, is_tx_missing_auth ); - + auto a3only = vector{{"acc3","active"}}; - BOOST_CHECK_EXCEPTION( CALL_TEST_FUNCTION( TEST_METHOD(test_message, 6), {}, a3only), + BOOST_CHECK_EXCEPTION( CALL_TEST_FUNCTION( TEST_METHOD(test_message, require_auth), {}, a3only, {}), tx_missing_auth, is_tx_missing_auth ); auto a4only = vector{{"acc4","active"}}; - BOOST_CHECK_EXCEPTION( CALL_TEST_FUNCTION( TEST_METHOD(test_message, 6), {}, a4only), + BOOST_CHECK_EXCEPTION( CALL_TEST_FUNCTION( TEST_METHOD(test_message, require_auth), {}, a4only, {}), tx_missing_auth, is_tx_missing_auth ); auto a3a4 = vector{{"acc3","active"}, {"acc4","active"}}; - BOOST_CHECK_MESSAGE( CALL_TEST_FUNCTION( TEST_METHOD(test_message, 6), {}, a3a4 ) == WASM_TEST_PASS, "test_message::test6()"); + BOOST_CHECK_MESSAGE( CALL_TEST_FUNCTION( TEST_METHOD(test_message, require_auth), {}, a3a4, {} ) == WASM_TEST_PASS, "test_message::require_auth()"); - - BOOST_CHECK_EXCEPTION( CALL_TEST_FUNCTION( TEST_METHOD(test_message, 7), {}, {}), + BOOST_CHECK_EXCEPTION( CALL_TEST_FUNCTION( TEST_METHOD(test_message, assert_false), {}, {}, {}), fc::assert_exception, is_assert_exception ); - BOOST_CHECK_MESSAGE( CALL_TEST_FUNCTION( TEST_METHOD(test_message, 8), {}, {} ) == WASM_TEST_PASS, "test_message::test8()"); - + BOOST_CHECK_MESSAGE( CALL_TEST_FUNCTION( TEST_METHOD(test_message, assert_true), {}, {}, {} ) == WASM_TEST_PASS, "test_message::assert_true()"); chain.produce_blocks(1); uint32_t now = chain.head_block_time().sec_since_epoch(); - BOOST_CHECK_MESSAGE( CALL_TEST_FUNCTION2( TEST_METHOD(test_message, 9), {}, {}, now) == WASM_TEST_PASS, "test_message::test9()"); + BOOST_CHECK_MESSAGE( CALL_TEST_FUNCTION( TEST_METHOD(test_message, now), {}, {}, fc::raw::pack(now)) == WASM_TEST_PASS, "test_message::now()"); chain.produce_blocks(1); - BOOST_CHECK_MESSAGE( CALL_TEST_FUNCTION2( TEST_METHOD(test_message, 9), {}, {}, now) == WASM_TEST_FAIL, "test_message::test9()"); + BOOST_CHECK_MESSAGE( CALL_TEST_FUNCTION( TEST_METHOD(test_message, now), {}, {}, fc::raw::pack(now)) == WASM_TEST_FAIL, "test_message::now()"); + + //Test print + CAPTURE(cerr, CALL_TEST_FUNCTION( TEST_METHOD(test_print, test_prints), {}, {}, {}) ); + + BOOST_CHECK_EQUAL( last_fnc_err , WASM_TEST_PASS); + BOOST_CHECK_EQUAL( capture.size() , 3); + BOOST_CHECK_EQUAL( (capture[0] == "ab" && capture[1] == "c" && capture[2] == "efg") , true); + + auto U64Str = [](uint64_t v) -> std::string { + std::stringstream s; + s << v; + return s.str(); + }; + + CAPTURE(cerr, CALL_TEST_FUNCTION( TEST_METHOD(test_print, test_printi), {}, {}, {}) ); + BOOST_CHECK_EQUAL( capture.size() , 3); + BOOST_CHECK_EQUAL( capture[0], U64Str(0) ); + BOOST_CHECK_EQUAL( capture[1], U64Str(556644) ); + BOOST_CHECK_EQUAL( capture[2], U64Str(-1) ); + + auto U128Str = [](uint128_t value) -> std::string { + fc::uint128_t v(value>>64, uint64_t(value) ); + return fc::variant(v).get_string(); + }; + + CAPTURE(cerr, CALL_TEST_FUNCTION( TEST_METHOD(test_print, test_printi128), {}, {}, {}) ); + BOOST_CHECK_EQUAL( capture.size() , 3); + BOOST_CHECK_EQUAL( capture[0], U128Str(-1)); + BOOST_CHECK_EQUAL( capture[1], U128Str(0)); + BOOST_CHECK_EQUAL( capture[2], U128Str(87654323456)); + + CAPTURE(cerr, CALL_TEST_FUNCTION( TEST_METHOD(test_print, test_printn), {}, {}, {}) ); + BOOST_CHECK_EQUAL( capture.size() , 8); + BOOST_CHECK_EQUAL( ( + capture[0] == "abcde" && + capture[1] == "ab.de" && + capture[2] == "1q1q1q" && + capture[3] == "abcdefghijk" && + capture[4] == "abcdefghijkl" && + capture[5] == "abcdefghijklm" && + capture[6] == "abcdefghijklm" && + capture[7] == "abcdefghijklm" + ), true); + + //Test math + std::random_device rd; + std::mt19937_64 gen(rd()); + std::uniform_int_distribution dis; + + for(int i=0; i<10; i++) { + u128_msg msg; + msg.values[0] = dis(gen); msg.values[0] <<= 64; msg.values[0] |= dis(gen); + msg.values[1] = dis(gen); msg.values[1] <<= 64; msg.values[1] |= dis(gen); + msg.values[2] = msg.values[0] * msg.values[1]; + BOOST_CHECK_MESSAGE( CALL_TEST_FUNCTION( TEST_METHOD(test_math, test_multeq_i128), {}, {}, fc::raw::pack(msg) ) == WASM_TEST_PASS, "test_math::test_multeq_i128()" ); + } + + for(int i=0; i<10; i++) { + u128_msg msg; + msg.values[0] = dis(gen); msg.values[0] <<= 64; msg.values[0] |= dis(gen); + msg.values[1] = dis(gen); msg.values[1] <<= 64; msg.values[1] |= dis(gen); + msg.values[2] = msg.values[0] / msg.values[1]; + BOOST_CHECK_MESSAGE( CALL_TEST_FUNCTION( TEST_METHOD(test_math, test_diveq_i128), {}, {}, fc::raw::pack(msg) ) == WASM_TEST_PASS, "test_math::test_diveq_i128()" ); + } + + BOOST_CHECK_EXCEPTION( CALL_TEST_FUNCTION( TEST_METHOD(test_math, test_diveq_i128_by_0), {}, {}, {} ), + fc::assert_exception, is_assert_exception ); + + //Test db + const auto& idx = chain_db.get_index(); + + BOOST_CHECK_MESSAGE( CALL_TEST_FUNCTION( TEST_METHOD(test_db, key_i64_general), {}, {}, {} ) == WASM_TEST_PASS, "test_db::key_i64_general()" ); + BOOST_CHECK_EQUAL( std::distance(idx.begin(), idx.end()) , 4); + + auto itr = idx.lower_bound( boost::make_tuple( N(test_api), N(test_api), N(test_table)) ); + + BOOST_CHECK_EQUAL((uint64_t)itr->key, N(alice)); ++itr; + BOOST_CHECK_EQUAL((uint64_t)itr->key, N(bob)); ++itr; + BOOST_CHECK_EQUAL((uint64_t)itr->key, N(carol)); ++itr; + BOOST_CHECK_EQUAL((uint64_t)itr->key, N(dave)); + + BOOST_CHECK_MESSAGE( CALL_TEST_FUNCTION( TEST_METHOD(test_db, key_i64_remove_all), {}, {}, {} ) == WASM_TEST_PASS, "test_db::key_i64_remove_all()" ); + BOOST_CHECK_EQUAL( std::distance(idx.begin(), idx.end()) , 0); + + BOOST_CHECK_EXCEPTION( CALL_TEST_FUNCTION( TEST_METHOD(test_db, key_i64_small_load), {}, {}, {} ), + fc::assert_exception, is_assert_exception ); + + BOOST_CHECK_EXCEPTION( CALL_TEST_FUNCTION( TEST_METHOD(test_db, key_i64_small_store), {}, {}, {} ), + fc::assert_exception, is_assert_exception ); + + BOOST_CHECK_EXCEPTION( CALL_TEST_FUNCTION_SCOPE( TEST_METHOD(test_db, key_i64_store_scope), {}, {}, {}, {N(another)} ), + tx_missing_scope, is_tx_missing_scope ); + + BOOST_CHECK_EXCEPTION( CALL_TEST_FUNCTION_SCOPE( TEST_METHOD(test_db, key_i64_remove_scope), {}, {}, {}, {N(another)} ), + tx_missing_scope, is_tx_missing_scope ); + BOOST_CHECK_MESSAGE( CALL_TEST_FUNCTION( TEST_METHOD(test_db, key_i64_not_found), {}, {}, {} ) == WASM_TEST_PASS, "test_db::key_i64_not_found()" ); } FC_LOG_AND_RETHROW() } -- GitLab