Skip to content
This repository was archived by the owner on Aug 2, 2022. It is now read-only.

eosiolib Unit/Regression Tests #424

Merged
merged 55 commits into from
Feb 21, 2019
Merged
Changes from 1 commit
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
e703cc3
Add more `name` tests
Dec 28, 2018
f236e89
Merge branch 'release/1.5.x' into cdt-tests
Jan 2, 2019
5d83272
Start tests
Jan 2, 2019
ceab265
Merge remote-tracking branch 'upstream/larryk85-patch-1' into cdt-tests
Jan 3, 2019
cd1def0
Continuation of `name` type tests
Jan 3, 2019
3c16d75
Continuation of `name` type tests
Jan 4, 2019
c0703b0
Start `symbol` type tests
Jan 7, 2019
a536473
Start `asset` type tests
Jan 8, 2019
dfa7b9d
Continuation of `asset` type tests
Jan 9, 2019
09c8222
Continuation of `asset` type tests
Jan 11, 2019
86397cf
Continuation of `asset` type tests
Jan 11, 2019
0b458b2
Start `microseconds`, `time_point`, and `time_point_sec` type tests
Jan 15, 2019
39845b0
Refactor tests to be more succinct
Jan 17, 2019
e65b747
Continue refactor of tests for clarity and templates for future tests
Jan 18, 2019
897627f
Start varint and print tests
Jan 23, 2019
b486c4d
Update `CMakeLists.txt` files
Jan 24, 2019
65783b9
Add `fixed_bytes` and `crypto` tests
Jan 25, 2019
f5bed23
Add `datastream` tests
Jan 28, 2019
62d5140
Continuation of `datastream` tests
Jan 28, 2019
63c1d9a
Progress on `datastream` tests and `varint` tests almost done
Jan 28, 2019
253297a
Continuing work on `fixed_bytes` tests
Jan 29, 2019
751f9fe
Add `binary_extension` tests
Jan 29, 2019
0aab645
Continuation
Jan 30, 2019
b5d8b43
Continuation of `datastream` tests
Jan 30, 2019
f35f6af
Tidy up tests;
Jan 31, 2019
5e4b003
Continuation of `datastream` tests
Feb 1, 2019
80e9fae
Continuation of `datastream` tests
Feb 4, 2019
23f1734
Continuation of `datastream` tests
Feb 4, 2019
e0484fa
Fix alignment issue
Feb 4, 2019
3e44872
Finishing up `datastream` tests
Feb 5, 2019
1c2935a
Tidy up `datastream` tests
Feb 6, 2019
7993563
Start trying to touch-up `varint` tests
Feb 6, 2019
6140d28
Fix build with `fno-builtins` flag
Feb 7, 2019
d2accfe
Finishing up `datastream` tests
Feb 7, 2019
bef0fca
Delete .#CMakeLists.txt
johndebord Feb 7, 2019
3ccea4d
More edits on `datastream` tests
Feb 8, 2019
14a2e1c
Merge branch 'cdt-tests' of github.com:EOSIO/eosio.cdt into cdt-tests
Feb 8, 2019
bd76516
Finish `datastream` tests
Feb 8, 2019
2bcd19a
Finish `datastream` tests
Feb 8, 2019
0cc99ce
Spruce-up tests
Feb 8, 2019
e1deefb
Fix for `__bzero` behavior
Feb 11, 2019
677d158
Finish `serialize_tests`
Feb 11, 2019
7cb0f54
Nearly finished with `time_tests`; with various other edits
Feb 14, 2019
c87404b
Finish `time_tests` and `varint_tests`
Feb 15, 2019
c717257
Continuation of `fixed_bytes_tests.cpp`
Feb 16, 2019
61df416
Finish tests and get them production ready
Feb 19, 2019
4c2c6b0
merged release/1.6.x
larryk85 Feb 19, 2019
0de3c41
added llp64 fixes and fixed sse issues
larryk85 Feb 20, 2019
bb32d45
remove unneeded code
larryk85 Feb 20, 2019
f29d37e
use size_t and uint64_t for malloc instead of uint32_t and int32_t
larryk85 Feb 21, 2019
33bf11a
Add conr2d's changes and update `asset_tests`
Feb 21, 2019
107fbb2
Clean up
Feb 21, 2019
e969ad9
Fix to silence conversion warning
Feb 21, 2019
25ecd4c
Remove `string` dependency
johndebord Feb 21, 2019
e5be3b2
Expound upon `signed_int` test
Feb 21, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Start microseconds, time_point, and time_point_sec type tests
johndebord committed Jan 15, 2019
commit 0b458b21f35a1380c350e8b0a487a195378061f1
193 changes: 84 additions & 109 deletions libraries/eosiolib/name.hpp
Original file line number Diff line number Diff line change
@@ -4,8 +4,8 @@
*/
#pragma once

#include "serialize.hpp"
#include "system.hpp"
#include "serialize.hpp"

#include <string>
#include <string_view>
@@ -30,63 +30,62 @@ namespace eosio {
/**
* Construct a new name
*
* @brief Construct a new name object with a default value of 0
* @brief Construct a new name object defaulting to a value of 0
*
*/
constexpr name()
: value{}
{}
constexpr name() : value(0) {}

/**
* Construct a new name given a unit64_t value
*
* @brief Construct a new name object initialising value with val
* @param val - The unit64_t value
* @brief Construct a new name object initialising value with v
* @param v - The unit64_t value
*
*/
constexpr explicit name( uint64_t val )
: value{val}
constexpr explicit name( uint64_t v )
:value(v)
{}

/**
* Construct a new name with a scoped enumerated type of raw uint64_t.
* Construct a new name given a scoped enumerated type of raw (uint64_t).
*
* @brief Construct a new name object, initialising value with r
* @brief Construct a new name object initialising value with r
* @param r - The raw value which is a scoped enumerated type of unit64_t
*
*/
constexpr explicit name( name::raw r )
: value(static_cast<uint64_t>(r))
:value(static_cast<uint64_t>(r))
{}

/**
* Construct a new name given an string.
*
* @brief Construct a new name object, initialising value with str
* @param str - The string value which validates and converts to a unit64_t
* @brief Construct a new name object initialising value with str
* @param str - The string value which validated then converted to unit64_t
*
*/
constexpr explicit name( std::string_view str )
: value{0}
:value(0)
{
if( 13 < str.size() )
if( str.size() > 13 ) {
eosio::check( false, "string is too long to be a valid name" );
if( str.empty() )
}
if( str.empty() ) {
return;
}

uint8_t length = (12 < str.size()) ? 12 : str.size();

for( decltype(length) i = 0; i < length; ++i ) {
auto n = std::min( (uint32_t)str.size(), (uint32_t)12u );
for( decltype(n) i = 0; i < n; ++i ) {
value <<= 5;
value |= char_to_value( str[i] );
}
value <<= ( 4 + 5*(12 - length) );

value <<= ( 4 + 5*(12 - n) );
if( str.size() == 13 ) {
uint64_t val = char_to_value( str[12] );
if( 0x0FULL < val )
uint64_t v = char_to_value( str[12] );
if( v > 0x0Full ) {
eosio::check(false, "thirteenth character in name cannot be a letter that comes after j");
value |= val;
}
value |= v;
}
}

@@ -96,67 +95,68 @@ namespace eosio {
* @param c - Character to be converted
* @return constexpr char - Converted value
*/
static constexpr uint8_t char_to_value( char ch ) {
switch(ch) {
case '.':
return 0;
break;
case '1' ... '5':
return (ch - '1') + 1;
break;
case 'a' ... 'z':
return (ch - 'a') + 6;
break;
default:
eosio::check( false, "character is not in allowed character set for names" );
}
static constexpr uint8_t char_to_value( char c ) {
if( c == '.')
return 0;
else if( c >= '1' && c <= '5' )
return (c - '1') + 1;
else if( c >= 'a' && c <= 'z' )
return (c - 'a') + 6;
else
eosio::check( false, "character is not in allowed character set for names" );

return 0; // control flow will never reach here; just added to suppress warning
}

/**
* Returns the length of the %name
*/
constexpr uint8_t length()const {
constexpr uint64_t mask = 0xF800000000000000ull;

if( value == 0 )
return 0;

constexpr uint64_t mask{0xF800000000000000ULL};

uint64_t val{value};
uint8_t length{};
for( uint8_t i{}; i < 13; val <<= 5, ++i )
if( 0 < (val & mask) )
length = i;
return length + 1;

uint8_t l = 0;
uint8_t i = 0;
for( auto v = value; i < 13; ++i, v <<= 5 ) {
if( (v & mask) > 0 ) {
l = i;
}
}

return l + 1;
}

/**
* Returns the suffix of the %name
*/
constexpr name suffix()const {
uint32_t remaining_bits_after_last_actual_dot{};
uint32_t tmp{};
for( int32_t remaining_bits{59}; 4 <= remaining_bits; remaining_bits -= 5 ) { // Remaining_bits must remain signed integer
// Get characters in name, one-by-one, in order from left to right (not including the 13th character)
uint8_t ch = (value >> remaining_bits) & 0x1FULL;
if( ch ) // if this character is not a dot
remaining_bits_after_last_actual_dot = tmp;
else // if this character is a dot
uint32_t remaining_bits_after_last_actual_dot = 0;
uint32_t tmp = 0;
for( int32_t remaining_bits = 59; remaining_bits >= 4; remaining_bits -= 5 ) { // Note: remaining_bits must remain signed integer
// Get characters one-by-one in name in order from left to right (not including the 13th character)
auto c = (value >> remaining_bits) & 0x1Full;
if( !c ) { // if this character is a dot
tmp = static_cast<uint32_t>(remaining_bits);
} else { // if this character is not a dot
remaining_bits_after_last_actual_dot = tmp;
}
}

uint64_t thirteenth_character{value & 0x0FULL};
if( thirteenth_character ) // if 13th character is not a dot
uint64_t thirteenth_character = value & 0x0Full;
if( thirteenth_character ) { // if 13th character is not a dot
remaining_bits_after_last_actual_dot = tmp;
}

if( remaining_bits_after_last_actual_dot == 0 ) // there is no actual dot in the %name other than potentially leading dots
return name{value};

// At this point remaining_bits_after_last_actual_dot has to be within the range of 4 to 59 (and restricted to increments of 5)
// At this point remaining_bits_after_last_actual_dot has to be within the range of 4 to 59 (and restricted to increments of 5).

// Mask for remaining bits corresponding to characters after last actual dot, except for 4 least significant bits (corresponds to 13th character)
uint64_t mask{(1ULL << remaining_bits_after_last_actual_dot) - 16};
uint32_t shift{64 - remaining_bits_after_last_actual_dot};
// Mask for remaining bits corresponding to characters after last actual dot, except for 4 least significant bits (corresponds to 13th character).
uint64_t mask = (1ull << remaining_bits_after_last_actual_dot) - 16;
uint32_t shift = 64 - remaining_bits_after_last_actual_dot;

return name{ ((value & mask) << shift) + (thirteenth_character << (shift-1)) };
}
@@ -171,103 +171,78 @@ namespace eosio {
/**
* Explicit cast to bool of the uint64_t value of the name
*
* @return Returns true if the name is set to the default value of 0 else true
* @return Returns true if the name is set to the default value of 0 else true.
*/
constexpr explicit operator bool()const { return value != 0; }

/**
* Writes the %name as a string to char buffer
* Writes the %name as a string to the provided char buffer
*
* @pre Appropriate Size Precondition: (begin + 13) <= end and (begin + 13) does not overflow
* @pre Valid Memory Region Precondition: The range [begin, end) must be a valid range of memory to write to.
* @param begin - The start of the char buffer
* @param end - Just past the end of the char buffer
* @return char* - Just past the end of the last character written (returns begin if the Appropriate Size Precondition is not satisfied)
* @post If the Appropriate Size Precondition is satisfied, the range [begin, returned pointer) contains the string representation of the %name
* @post If the Appropriate Size Precondition is satisfied, the range [begin, returned pointer) contains the string representation of the %name.
*/
char* write_as_string( char* begin, char* end )const {
static const char* charmap{".12345abcdefghijklmnopqrstuvwxyz"};
constexpr uint64_t mask{0xF800000000000000ULL};
static const char* charmap = ".12345abcdefghijklmnopqrstuvwxyz";
constexpr uint64_t mask = 0xF800000000000000ull;

if( (begin + 13) < begin || end < (begin + 13) ) return begin;
if( (begin + 13) < begin || (begin + 13) > end ) return begin;

uint64_t val{value};
for( uint8_t i{}; i < 13; ++i, val <<= 5 ) {
if( val == 0 ) return begin;
auto v = value;
for( auto i = 0; i < 13; ++i, v <<= 5 ) {
if( v == 0 ) return begin;

uint8_t index = (val & mask) >> ((i == 12) ? 60 : 59);
*begin = charmap[index];
auto indx = (v & mask) >> (i == 12 ? 60 : 59);
*begin = charmap[indx];
++begin;
}

return begin;
}

/**
* Returns the name as a string.
*
* @brief Returns the name value as a string by calling write_as_string(); returning the buffer produced by write_as_string()
* @brief Returns the name value as a string by calling write_as_string() and returning the buffer produced by write_as_string()
*/
std::string to_string()const {
char buffer[13];
char* end{write_as_string( buffer, buffer + sizeof(buffer) )};
auto end = write_as_string( buffer, buffer + sizeof(buffer) );
return {buffer, end};
}

/**
* Equivalency operator. Returns true if a == b
* Equivalency operator. Returns true if a == b (are the same)
*
* @return boolean - true if both provided %name values are the same
*/
friend constexpr bool operator==( const name& a, const name& b ) {
friend constexpr bool operator == ( const name& a, const name& b ) {
return a.value == b.value;
}

/**
* Inverted equivalency operator. Returns true if a != b
* Inverted equivalency operator. Returns true if a != b (are different)
*
* @return boolean - true if both provided %name values are not the same
*/
friend constexpr bool operator!=( const name& a, const name& b ) {
friend constexpr bool operator != ( const name& a, const name& b ) {
return a.value != b.value;
}

/**
* Less than operator. Returns true if a < b
* Less than operator. Returns true if a < b.
*
* @return boolean - true if %name a is less than b
* @return boolean - true if %name `a` is less than `b`
*/
friend constexpr bool operator<( const name& a, const name& b ) {
friend constexpr bool operator < ( const name& a, const name& b ) {
return a.value < b.value;
}

/**
* Less than or equal to operator. Returns true if a <= b
*
* @return boolean - true if %name a is less than or equal to b
*/
friend constexpr bool operator<=( const name& a, const name& b ) {
return a.value <= b.value;
}

/**
* Greater than operator. Returns true if a > b
*
* @return boolean - true if %name a is greater than b
*/
friend constexpr bool operator>( const name& a, const name& b ) {
return a.value > b.value;
}

/**
* Greater than or equal to operator. Returns true if a >= b
*
* @return boolean - true if %name a is greater than or equal to b
*/
friend constexpr bool operator>=( const name& a, const name& b ) {
return a.value >= b.value;
}

uint64_t value{};
uint64_t value = 0;

EOSLIB_SERIALIZE( name, (value) )
};
54 changes: 27 additions & 27 deletions libraries/eosiolib/symbol.hpp
Original file line number Diff line number Diff line change
@@ -4,14 +4,14 @@
*/
#pragma once

#include "name.hpp"
#include "system.hpp"
#include "print.h"
#include "name.hpp"
#include "serialize.hpp"
#include "system.hpp"

#include <tuple>
#include <limits>
#include <string_view>
#include <tuple>

namespace eosio {

@@ -32,22 +32,20 @@ namespace eosio {
/**
* Default constructor, construct a new symbol_code
*
* @brief Construct a new symbol_code object with a default value of 0
* @brief Construct a new symbol_code object defaulting to a value of 0
*
*/
constexpr symbol_code()
: value{}
{}
constexpr symbol_code() : value(0) {}

/**
* Construct a new symbol_code with a scoped enumerated type of raw uint64_t.
* Construct a new symbol_code given a scoped enumerated type of raw (uint64_t).
*
* @brief Construct a new symbol_code object initialising value with raw
* @param raw - The raw value which is a scoped enumerated type of unit64_t
*
*/
constexpr explicit symbol_code( uint64_t raw )
: value{raw}
:value(raw)
{}

/**
@@ -58,13 +56,15 @@ namespace eosio {
*
*/
constexpr explicit symbol_code( std::string_view str )
: value{}
:value(0)
{
if( 7 < str.size() )
if( str.size() > 7 ) {
eosio::check( false, "string is too long to be a valid symbol_code" );
}
for( auto itr = str.rbegin(); itr != str.rend(); ++itr ) {
if( *itr < 'A' || 'Z' < *itr )
if( *itr < 'A' || *itr > 'Z') {
eosio::check( false, "only uppercase letters allowed in symbol_code string" );
}
value <<= 8;
value |= *itr;
}
@@ -75,16 +75,16 @@ namespace eosio {
* @return true - if symbol is valid
*/
constexpr bool is_valid()const {
uint64_t sym{value};
for ( int i{}; i < 7; ++i ) {
char ch = static_cast<char>(sym & 0xFF);
if ( !('A' <= ch && ch <= 'Z') ) return false;
auto sym = value;
for ( int i=0; i < 7; i++ ) {
char c = (char)(sym & 0xFF);
if ( !('A' <= c && c <= 'Z') ) return false;
sym >>= 8;
if ( !(sym & 0xFF) ) {
do {
sym >>= 8;
if ( (sym & 0xFF) ) return false;
++i;
i++;
} while( i < 7 );
}
}
@@ -97,13 +97,13 @@ namespace eosio {
* @return length - character length of the provided symbol
*/
constexpr uint32_t length()const {
uint64_t sym{value};
uint32_t length{};
while (sym & 0xFF && length <= 7) {
++length;
auto sym = value;
uint32_t len = 0;
while (sym & 0xFF && len <= 7) {
len++;
sym >>= 8;
}
return length;
return len;
}

/**
@@ -133,15 +133,15 @@ namespace eosio {
* @post If the Appropriate Size Precondition is satisfied, the range [begin, returned pointer) contains the string representation of the symbol_code.
*/
char* write_as_string( char* begin, char* end )const {
constexpr uint64_t mask = 0xFFULL;
constexpr uint64_t mask = 0xFFull;

if( (begin + 7) < begin || (begin + 7) > end ) return begin;

auto val = value;
for( auto i = 0; i < 7; ++i, val >>= 8 ) {
if( val == 0 ) return begin;
auto v = value;
for( auto i = 0; i < 7; ++i, v >>= 8 ) {
if( v == 0 ) return begin;

*begin = static_cast<char>(val & mask);
*begin = static_cast<char>(v & mask);
++begin;
}

2 changes: 1 addition & 1 deletion tests/unit/asset_tests.cpp
Original file line number Diff line number Diff line change
@@ -408,7 +408,7 @@ EOSIO_TEST_BEGIN(extended_asset_type_test)
silence_output(false);
EOSIO_TEST_END

int main(int argc, char** argv) {
int main(int argc, char* argv[]) {
EOSIO_TEST(asset_type_test);
EOSIO_TEST(extended_asset_type_test);
return has_failed();
126 changes: 1 addition & 125 deletions tests/unit/name_tests.cpp
Original file line number Diff line number Diff line change
@@ -370,131 +370,7 @@ EOSIO_TEST_BEGIN(name_type_test)
silence_output(false);
EOSIO_TEST_END

// // Intrinsics defined in `eos/libraries/chain/wasm_interface.cpp` that involve the `name` type
// // Defined in `eos/libraries/chain/wasm_interface.cpp`
// EOSIO_TEST_BEGIN(set_resource_limits_intrinsic_test)
// intrinsics::set_intrinsic<intrinsics::set_resource_limits>([](name account, int64_t ram_bytes, int64_t net_weight, int64_t cpu_weight) {

// });
// EOSIO_TEST_END

// // Defined in `eos/libraries/chain/wasm_interface.cpp`
// EOSIO_TEST_BEGIN(get_resource_limits_intrinsic_test)
// intrinsics::set_intrinsic<intrinsics::get_resource_limits>([](name account, int64_t ram_bytes, int64_t net_weight, int64_t cpu_weight) {

// });
// EOSIO_TEST_END

// // Defined in `eos/libraries/chain/wasm_interface.cpp`
// EOSIO_TEST_BEGIN(set_proposed_producers_intrinsic_test)
// intrinsics::set_intrinsic<intrinsics::set_proposed_producers>([](uint64_t a) {

// });
// EOSIO_TEST_END

// // Defined in `eos/libraries/chain/wasm_interface.cpp`
// EOSIO_TEST_BEGIN(is_privileged_intrinsic_test)
// intrinsics::set_intrinsic<intrinsics::is_privileged>([](uint64_t a) {

// });
// EOSIO_TEST_END

// // Defined in `eos/libraries/chain/wasm_interface.cpp`
// EOSIO_TEST_BEGIN(set_privileged_intrinsic_test)
// intrinsics::set_intrinsic<intrinsics::set_privileged>([](uint64_t a) {

// });
// EOSIO_TEST_END

// // Defined in `eos/libraries/chain/wasm_interface.cpp`
// EOSIO_TEST_BEGIN(get_active_producers_intrinsic_test)
// intrinsics::set_intrinsic<intrinsics::get_active_producers>([](uint64_t a) {

// });
// EOSIO_TEST_END

// // Defined in `eos/libraries/chain/wasm_interface.cpp`
// EOSIO_TEST_BEGIN(check_permission_authorization_intrinsic_test)
// intrinsics::set_intrinsic<intrinsics::check_permission_authorization>([](uint64_t a) {

// });
// EOSIO_TEST_END

// // Defined in `eos/libraries/chain/wasm_interface.cpp`
// EOSIO_TEST_BEGIN(get_permission_last_used_intrinsic_test)
// intrinsics::set_intrinsic<intrinsics::get_permission_last_used>([](uint64_t a) {

// });
// EOSIO_TEST_END

// // Defined in `eos/libraries/chain/wasm_interface.cpp`
// EOSIO_TEST_BEGIN(get_account_creation_time_intrinsic_test)
// intrinsics::set_intrinsic<intrinsics::get_account_creation_time>([](uint64_t a) {

// });
// EOSIO_TEST_END

// // Defined in `eos/libraries/chain/wasm_interface.cpp`
// EOSIO_TEST_BEGIN(get_permission_last_used_intrinsic_test)
// intrinsics::set_intrinsic<intrinsics::get_permission_last_used>([](uint64_t a) {

// });
// EOSIO_TEST_END

// // Defined in `eos/libraries/chain/wasm_interface.cpp`
// EOSIO_TEST_BEGIN(require_authorization_intrinsic_test)
// intrinsics::set_intrinsic<intrinsics::require_authorization>([](uint64_t a) {

// });
// EOSIO_TEST_END

// // Defined in `eos/libraries/chain/wasm_interface.cpp`
// EOSIO_TEST_BEGIN(has_authorization_intrinsic_test)
// intrinsics::set_intrinsic<intrinsics::has_authorization>([](uint64_t a) {

// });
// EOSIO_TEST_END

// // Defined in `eos/libraries/chain/wasm_interface.cpp`
// EOSIO_TEST_BEGIN(require_recipient_intrinsic_test)
// intrinsics::set_intrinsic<intrinsics::require_recipient>([](uint64_t a) {

// });
// EOSIO_TEST_END

// // Defined in `eos/libraries/chain/wasm_interface.cpp`
// EOSIO_TEST_BEGIN(is_account_intrinsic_test)
// intrinsics::set_intrinsic<intrinsics::is_account>([](uint64_t a) {

// });
// EOSIO_TEST_END

// // Defined in `eos/libraries/chain/wasm_interface.cpp`
// EOSIO_TEST_BEGIN(send_deferred_intrinsic_test)
// intrinsics::set_intrinsic<intrinsics::send_deferred>([](uint64_t a) {

// });
// EOSIO_TEST_END

// EOSIO_TEST_BEGIN(is_account_test)
// intrinsics::set_intrinsic<intrinsics::is_account>([](uint64_t a) {
// if (a == 3)
// return true;
// if (a == 4)
// return true;
// return false;
// });

// CHECK_ASSERT("is not an account", ([]() {
// eosio_assert(is_account(5), "is not an account");
// }));
// CHECK_EQUAL(is_account(3), true);
// CHECK_EQUAL(is_account(4), true);
// CHECK_EQUAL(is_account(6), true);
// REQUIRE_EQUAL(is_account(7), true);
// EOSIO_TEST_END

int main(int argc, char** argv) {
int main(int argc, char* argv[]) {
EOSIO_TEST(name_type_test);
return has_failed();
}
10 changes: 9 additions & 1 deletion tests/unit/symbol_tests.cpp
Original file line number Diff line number Diff line change
@@ -106,10 +106,14 @@ EOSIO_TEST_BEGIN(symbol_code_type_test)
REQUIRE_EQUAL( symbol_code{0} < symbol_code{"Z"}, true );
REQUIRE_EQUAL( symbol_code{0} < symbol_code{"AAAAAAA"}, true );
REQUIRE_EQUAL( symbol_code{0} < symbol_code{"ZZZZZZZ"}, true );

silence_output(false);
EOSIO_TEST_END

// Defined in `eosio.cdt/libraries/eosiolib/symbol.hpp`
EOSIO_TEST_BEGIN(symbol_type_test)
silence_output(true);

// ------------------------------------------
// constructors/constexpr uint64_t raw()const

@@ -210,10 +214,14 @@ EOSIO_TEST_BEGIN(symbol_type_test)
REQUIRE_EQUAL( (symbol{0} < symbol{"Z",0}), true );
REQUIRE_EQUAL( (symbol{0} < symbol{"AAAAAAA",0}), true );
REQUIRE_EQUAL( (symbol{0} < symbol{"ZZZZZZZ",0}), true );

silence_output(false);
EOSIO_TEST_END

// Defined in `eosio.cdt/libraries/eosiolib/symbol.hpp`
EOSIO_TEST_BEGIN(extended_symbol_type_test)
silence_output(true);

// ------------------------------------
// constructors/get_symbol/get_contract

@@ -277,7 +285,7 @@ EOSIO_TEST_BEGIN(extended_symbol_type_test)
silence_output(false);
EOSIO_TEST_END

int main(int argc, char** argv) {
int main(int argc, char* argv[]) {
EOSIO_TEST(symbol_code_type_test);
EOSIO_TEST(symbol_type_test);
EOSIO_TEST(extended_symbol_type_test);
300 changes: 300 additions & 0 deletions tests/unit/time_tests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,300 @@
#include <eosiolib/eosio.hpp>
#include <eosio/native/tester.hpp>

#include <eosiolib/time.hpp>

using eosio::microseconds;
using eosio::time_point;
using eosio::time_point_sec;

using namespace eosio::native;

const uint32_t u32MAX = std::numeric_limits<uint32_t>::max(); // 18446744073709551615
const uint32_t u32MIN = std::numeric_limits<uint32_t>::min(); // 0

const int64_t i64MAX = std::numeric_limits<int64_t>::max(); // 9223372036854775807
const int64_t i64MIN = std::numeric_limits<int64_t>::min(); // -9223372036854775808

// This is interesting. `print_f` won't print the '-' character.
// `printf` won't print anything.
// `printf("%\n",i64MIN);`

// Note that there are no invariants established to protect this type against overflow.
// For example: if you define a microsecond type from i64MAX and then check that value in
// Or if you check the `seconds` of a (u64MAX / 1000000 + 1), it will overflow.
// Potentially could be abused in a contract?

// Defined in `eosio.cdt/libraries/eosiolib/time.hpp`
EOSIO_TEST_BEGIN(microseconds_type_test)
silence_output(false);

// ------------
// constructors

// -----------------------------------------------
/// explicit microseconds(uint64_t)/int64_t count()
REQUIRE_EQUAL( microseconds{}.count(), 0ULL )
REQUIRE_EQUAL( microseconds{i64MAX}.count(), i64MAX )
REQUIRE_EQUAL( microseconds{i64MIN}.count(), i64MIN )

// -----------------------------
// static microseconds maximum()
REQUIRE_EQUAL( microseconds::maximum().count(), microseconds{0x7FFFFFFFFFFFFFFFLL}.count() )

// ------------------------------------------------------------------------
// friend microseconds operator+(const microseconds&, const microseconds&)
// friend microseconds operator-(const microseconds&, const microseconds&)
REQUIRE_EQUAL( (microseconds{0LL} + microseconds{1LL}), microseconds{1LL} )
REQUIRE_EQUAL( (microseconds{0LL} - microseconds{1LL}), microseconds{-1LL} )

// -------------------------------------
// bool operator==(const microseconds&)
// bool operator!=(const microseconds&)
// bool operator<(const microseconds&)
// bool operator<=(const microseconds&)
// bool operator>(const microseconds&)
// bool operator>=(const microseconds&)
REQUIRE_EQUAL( (microseconds{1LL} == microseconds{1LL}), true )
REQUIRE_EQUAL( (microseconds{1LL} != microseconds{0LL}), true )
REQUIRE_EQUAL( (microseconds{0LL} < microseconds{1LL}), true )
REQUIRE_EQUAL( (microseconds{1LL} <= microseconds{1LL}), true )
REQUIRE_EQUAL( (microseconds{1LL} > microseconds{0LL}), true )
REQUIRE_EQUAL( (microseconds{1LL} >= microseconds{1LL}), true )

// ----------------------------------------------
// microseconds& operator+=(const microseconds&)
// microseconds& operator-=(const microseconds&)
REQUIRE_EQUAL( (microseconds{0LL} += microseconds{1LL}), microseconds{1LL} )
REQUIRE_EQUAL( (microseconds{0LL} -= microseconds{1LL}), microseconds{-1LL} )

// --------------------
// int64_t to_seconds()
REQUIRE_EQUAL( (microseconds{i64MAX}.to_seconds()), i64MAX / 1000000 )

// ------------------------------------
// inline microseconds seconds(int64_t)
// inline microseconds milliseconds(int64_t)
// inline microseconds minutes(int64_t)
// inline microseconds hours(int64_t)
// inline microseconds days(int64_t)
REQUIRE_EQUAL( eosio::seconds(60LL), microseconds{60LL*1000000LL} )
REQUIRE_EQUAL( eosio::milliseconds(60LL), microseconds{60LL*1000LL} )
REQUIRE_EQUAL( eosio::minutes(60LL), microseconds{60LL*60LL*1000000LL} )
REQUIRE_EQUAL( eosio::hours(60LL), microseconds{60LL*60LL*60LL*1000000LL} )
REQUIRE_EQUAL( eosio::days(60LL), microseconds{24LL*60LL*60LL*60LL*1000000LL} )

silence_output(false);
EOSIO_TEST_END

EOSIO_TEST_BEGIN(time_point_type_test)
silence_output(true);

// ------------
// constructors
microseconds ms0{0LL};
microseconds ms1{1LL};
microseconds ms2{-1LL};
microseconds ms_max{i64MAX};
microseconds ms_min{i64MIN};

/// explicit time_point(microseconds)/microseconds& time_since_epoch()
REQUIRE_EQUAL( time_point{ms0}.time_since_epoch(), ms0 )
REQUIRE_EQUAL( time_point{ms1}.time_since_epoch(), ms1 )

// --------------------------
// uint32_t sec_since_epoch()
REQUIRE_EQUAL( time_point{ms0}.sec_since_epoch(), 0 / 1000000 )
REQUIRE_EQUAL( time_point{ms1}.sec_since_epoch(), 1 / 1000000 )
REQUIRE_EQUAL( time_point{ms_max}.sec_since_epoch(), i64MAX / 1000000 )
REQUIRE_EQUAL( time_point{ms_min}.sec_since_epoch(), i64MIN / 1000000 )

// -----------------------------------
// bool operator==(const time_point&)
// bool operator!=(const time_point&)
// bool operator<(const time_point&)
// bool operator<=(const time_point&)
// bool operator>(const time_point&)
// bool operator>=(const time_point&)
REQUIRE_EQUAL( (time_point{ms0} == time_point{ms0}), true )
REQUIRE_EQUAL( (time_point{ms1} != time_point{ms0}), true )
REQUIRE_EQUAL( (time_point{ms0} < time_point{ms1}), true )
REQUIRE_EQUAL( (time_point{ms1} <= time_point{ms1}), true )
REQUIRE_EQUAL( (time_point{ms1} > time_point{ms0}), true )
REQUIRE_EQUAL( (time_point{ms1} >= time_point{ms1}), true )

// --------------------------------------------
// time_point& operator+=(const microseconds&)
// time_point& operator-=(const microseconds&)
REQUIRE_EQUAL( (time_point{ms0} += ms1), time_point{ms1} )
REQUIRE_EQUAL( (time_point{ms0} -= ms1), time_point{ms2} )

// ------------------------------------------
// time_point operator+(const microseconds&)
// time_point operator+(const time_point&)
// time_point operator-(const microseconds&)
// microseconds operator-(const time_point&)
REQUIRE_EQUAL( (time_point{ms0} + ms1), time_point{ms1} )
REQUIRE_EQUAL( (time_point{ms0} + time_point{ms1}), time_point{ms1} )
REQUIRE_EQUAL( (time_point{ms0} - ms1), time_point{ms2} )
REQUIRE_EQUAL( (time_point{ms0} - time_point{ms1}), ms2 )

silence_output(false);
EOSIO_TEST_END

EOSIO_TEST_BEGIN(time_point_sec_type_test)
silence_output(false);

// ------------
// constructors
microseconds ms0{0LL};
microseconds ms1{1LL};
microseconds ms2{-1LL};
microseconds ms_max{i64MAX};
microseconds ms_min{i64MIN};

time_point tp0{ms0};
time_point tp1{ms1};
time_point tp2{ms2};
time_point tp_max{ms_max};
time_point tp_min{ms_min};

/// time_point_sec()/uint32_t sec_since_epoch()const
REQUIRE_EQUAL( time_point_sec{}.sec_since_epoch(), 0 )

/// explicit time_point_sec(uint32_t)
REQUIRE_EQUAL( time_point_sec{u32MAX}.sec_since_epoch(), u32MAX )
REQUIRE_EQUAL( time_point_sec{u32MAX + 1}.sec_since_epoch(), 0 )

/// time_point_sec(const time_point&)
REQUIRE_EQUAL( time_point_sec{tp0}.sec_since_epoch(), 0LL / 1000000LL )
REQUIRE_EQUAL( time_point_sec{tp1}.sec_since_epoch(), 1LL / 1000000LL )
REQUIRE_EQUAL( time_point_sec{tp2}.sec_since_epoch(), -1LL / 1000000LL )
REQUIRE_EQUAL( time_point_sec{tp_max}.sec_since_epoch(), i64MAX / 1000000LL )
REQUIRE_EQUAL( time_point_sec{tp_min}.sec_since_epoch(), i64MIN / 1000000LL )

// -------------------------------
// static time_point_sec maximum()
REQUIRE_EQUAL( time_point_sec{}.maximum().utc_seconds, 0xFFFFFFFF )
REQUIRE_EQUAL( time_point_sec{}.maximum().utc_seconds != 1, true )

// ---------------------------
// static time_point_sec min()
REQUIRE_EQUAL( time_point_sec{}.min().utc_seconds, 0 )
REQUIRE_EQUAL( time_point_sec{}.min().utc_seconds != 1, true )

// Millisecond data is lost when using these data types in certain ways.
// For Example:
// microseconds mms0{1};
// eosio::print_f("_count: %\n",mms0._count);
// time_point ttp0{mms0};
// eosio::print_f("_count: %\n",ttp0.elapsed._count);
// time_point_sec ttps0{ttp0};
// eosio::print_f("utc_seconds: %\n",ttps0.utc_seconds);
// ttp0 = ttps0;
// eosio::print_f("_count: %\n",ttp0.elapsed._count);
//
// Also may have found a `print_f` bug/
// To replicate:
// eosio::print_f("%", time_point{time_point_sec{tp_max}}.elapsed.count());
// eosio::print_f("%", 9223372036854775807 / 1000000);
// --------------------------
// operator time_point()const
REQUIRE_EQUAL( (time_point{time_point_sec{tp0}}.elapsed.count()), 0 )
REQUIRE_EQUAL( (time_point{time_point_sec{tp1}}.elapsed.count()), 0 )
REQUIRE_EQUAL( (time_point{time_point_sec{tp2}}.elapsed.count()), 0 )
REQUIRE_EQUAL( (time_point{time_point_sec{tp_max}}.elapsed._count / 1000000), ms_max.count() / 1000000 )
REQUIRE_EQUAL( (time_point{time_point_sec{tp_min}}.elapsed._count / 1000000), ms_min.count() / 1000000 )

// -------------------------------------------
// time_point_sec operator=(const time_point&)

// --------------------------------------------------------------------
// friend bool operator==(const time_point_sec&, const time_point_sec&)
// friend bool operator!=(const time_point_sec&, const time_point_sec&)
// friend bool operator<(const time_point_sec&, const time_point_sec&)
// friend bool operator<=(const time_point_sec&, const time_point_sec&)
// friend bool operator>(const time_point_sec&, const time_point_sec&)
// friend bool operator>=(const time_point_sec&, const time_point_sec&)
// REQUIRE_EQUAL( (time_point_sec{tp0} == time_point{tp0}), true )
// REQUIRE_EQUAL( (time_point_sec{tp1} != time_point{tp0}), true )
// REQUIRE_EQUAL( (time_point_sec{tp0} < time_point{tp1}), true )
// REQUIRE_EQUAL( (time_point_sec{tp1} <= time_point{tp1}), true )
// REQUIRE_EQUAL( (time_point_sec{tp1} > time_point{tp0}), true )
// REQUIRE_EQUAL( (time_point_sec{tp1} >= time_point{tp1}), true )


// ------------------------------------
// time_point_sec& operator+=(uint32_t)
// time_point_sec& operator+=(microseconds)
// time_point_sec& operator+=(time_point_sec)
// time_point_sec& operator-=(uint32_t)
// time_point_sec& operator-=(microseconds)
// time_point_sec& operator-=(time_point_sec)
// time_point_sec operator+(uint32_t)const
// time_point_sec operator-(uint32_t)const


// -----------------------------------------------------------------------
// friend time_point operator+(const time_point_sec&, const microseconds&)
// friend time_point operator-(const time_point_sec&, const microseconds&)
// friend microseconds operator-(const time_point_sec&, const time_point_sec&)
// friend microseconds operator-(const time_point&, const time_point_sec&)


silence_output(false);
EOSIO_TEST_END

EOSIO_TEST_BEGIN(block_timestamp_type_test)
silence_output(true);

// ------------
// constructors

/// explicit block_timestamp(uint32_t)

/// block_timestamp(const time_point&)

/// block_timestamp(const time_point&)

// --------------------------------
// static block_timestamp maximum()

// ----------------------------
// static block_timestamp min()

// ----------------------
// block_timestamp next()

// -------------------------------
// time_point to_time_point()const

// --------------------------
// operator time_point()const

// --------------------------------------
// void set_time_point(const time_point&)

// ------------------------------------------
// void set_time_point(const time_point_sec&)

// ---------------------------------
// void operator=(const time_point&)

// ---------------------------------------
// bool operator==(const block_timestamp&)
// bool operator!=(const block_timestamp&)
// bool operator<(const block_timestamp&)
// bool operator<=(const block_timestamp&)
// bool operator>(const block_timestamp&)
// bool operator>=(const block_timestamp&)

silence_output(false);
EOSIO_TEST_END

int main(int argc, char* argv[]) {
// EOSIO_TEST(microseconds_type_test);
// EOSIO_TEST(time_point_type_test);
EOSIO_TEST(time_point_sec_type_test);
// EOSIO_TEST(block_timestamp_type_test);
return has_failed();
}