Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
YottaChain
YTBP
提交
f21c658b
Y
YTBP
项目概览
YottaChain
/
YTBP
通知
0
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Y
YTBP
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
f21c658b
编写于
10月 16, 2017
作者:
D
Daniel Larimer
提交者:
GitHub
10月 16, 2017
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #536 from EOSIO/string-class
String class
上级
514ad71d
496c11c1
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
664 addition
and
2 deletion
+664
-2
contracts/eoslib/memory.h
contracts/eoslib/memory.h
+13
-0
contracts/eoslib/print.h
contracts/eoslib/print.h
+13
-0
contracts/eoslib/string.hpp
contracts/eoslib/string.hpp
+233
-0
contracts/test_api/test_api.cpp
contracts/test_api/test_api.cpp
+20
-1
contracts/test_api/test_api.hpp
contracts/test_api/test_api.hpp
+20
-0
contracts/test_api/test_string.cpp
contracts/test_api/test_string.cpp
+292
-0
libraries/chain/wasm_interface.cpp
libraries/chain/wasm_interface.cpp
+21
-1
tests/api_tests/api_tests.cpp
tests/api_tests/api_tests.cpp
+27
-0
tests/api_tests/memory_test/memory_test.cpp
tests/api_tests/memory_test/memory_test.cpp
+25
-0
未找到文件。
contracts/eoslib/memory.h
浏览文件 @
f21c658b
...
...
@@ -58,6 +58,19 @@ extern "C" {
*/
void
*
memcpy
(
void
*
destination
,
const
void
*
source
,
uint32_t
num
);
/**
* Compare block of memory from source to destination.
* @brief Copy a block of memory from source to destination.
* @param ptr1 Pointer to first data to compare
* @param ptr2 Pointer to second data to compare
* @param num Number of bytes to compare.
*
* @return the destination pointer
*
*/
int32_t
memcmp
(
void
*
ptr1
,
const
void
*
ptr2
,
uint32_t
num
);
/**
* Fill block of memory.
* @brief Fill a block of memory with the provided value.
...
...
contracts/eoslib/print.h
浏览文件 @
f21c658b
...
...
@@ -31,6 +31,19 @@ extern "C" {
*/
void
prints
(
const
char
*
cstr
);
/**
* Prints string up to given length
* @brief Prints string
* @param cstr - pointer to string
* @param len - len of string to be printed
*
* Example:
* @code
* prints_l("Hello World!", 5); // Output: Hello
* @endcode
*/
void
prints_l
(
const
char
*
cstr
,
uint32_t
len
);
/**
* Prints value as a 64 bit unsigned integer
* @brief Prints value as a 64 bit unsigned integer
...
...
contracts/eoslib/string.hpp
0 → 100644
浏览文件 @
f21c658b
#pragma once
#include <eoslib/types.hpp>
#include <eoslib/system.h>
#include <eoslib/memory.hpp>
#include <eoslib/print.hpp>
namespace
eos
{
class
string
{
private:
uint32_t
size
;
// size of the string
char
*
data
;
// underlying data
bool
own_memory
;
// true if the object is responsible to clean the memory
uint32_t
*
refcount
;
// shared reference count to the underlying data
// Release data if no more string reference to it
void
release_data_if_needed
()
{
if
(
own_memory
&&
refcount
!=
nullptr
)
{
(
*
refcount
)
--
;
if
(
*
refcount
==
0
)
{
free
(
data
);
}
}
}
public:
/**
* Default constructor
*/
string
()
:
size
(
0
),
data
(
nullptr
),
own_memory
(
false
),
refcount
(
nullptr
)
{
}
/**
* Constructor to create string with reserved space
* @param s size to be reserved (in number o)
*/
string
(
uint32_t
s
)
:
size
(
s
),
own_memory
(
true
)
{
data
=
(
char
*
)
malloc
(
s
*
sizeof
(
char
));
refcount
=
(
uint32_t
*
)
malloc
(
sizeof
(
uint32_t
));
*
refcount
=
1
;
}
/**
* Constructor to create string with given data and size
* @param d data
* @param s size of the string (in number of bytes)
* @param copy true to have the data copied and owned by the object
*/
string
(
char
*
d
,
uint32_t
s
,
bool
copy
)
{
assign
(
d
,
s
,
copy
);
}
// Copy constructor
string
(
const
string
&
obj
)
{
if
(
this
!=
&
obj
)
{
data
=
obj
.
data
;
size
=
obj
.
size
;
own_memory
=
obj
.
own_memory
;
refcount
=
obj
.
refcount
;
if
(
refcount
!=
nullptr
)
(
*
refcount
)
++
;
}
}
// Destructor
~
string
()
{
release_data_if_needed
();
}
// Get size of the string (in number of bytes)
const
uint32_t
get_size
()
const
{
return
size
;
}
// Get the underlying data of the string
const
char
*
get_data
()
const
{
return
data
;
}
// Check if it owns memory
const
bool
is_own_memory
()
const
{
return
own_memory
;
}
// Get the ref count
const
uint32_t
get_refcount
()
const
{
return
*
refcount
;
}
/**
* Assign string with new data and size
* @param d data
* @param s size (in number of bytes)
* @param copy true to have the data copied and owned by the object
* @return the current string
*/
string
&
assign
(
char
*
d
,
uint32_t
s
,
bool
copy
)
{
release_data_if_needed
();
if
(
copy
)
{
data
=
(
char
*
)
malloc
(
s
*
sizeof
(
char
));
memcpy
(
data
,
d
,
s
*
sizeof
(
char
));
own_memory
=
true
;
refcount
=
(
uint32_t
*
)
malloc
(
sizeof
(
uint32_t
));
*
refcount
=
1
;
}
else
{
data
=
d
;
own_memory
=
false
;
refcount
=
nullptr
;
}
size
=
s
;
return
*
this
;
}
/**
* Create substring from current string
* @param offset offset from the current string's data
* @param substr_size size of the substring
* @param copy true to have the data copied and owned by the object
* @return substring of the current string
*/
string
substr
(
uint32_t
offset
,
uint32_t
substr_size
,
bool
copy
)
{
assert
((
offset
<
size
)
&&
(
offset
+
substr_size
<
size
),
"out of bound"
);
return
string
(
data
+
offset
,
substr_size
,
copy
);
}
char
operator
[]
(
const
uint32_t
index
)
{
assert
(
index
<
size
,
"index out of bound"
);
return
*
(
data
+
index
);
}
string
&
operator
=
(
const
string
&
obj
)
{
if
(
this
!=
&
obj
)
{
release_data_if_needed
();
data
=
obj
.
data
;
size
=
obj
.
size
;
own_memory
=
obj
.
own_memory
;
refcount
=
obj
.
refcount
;
if
(
refcount
!=
nullptr
)
(
*
refcount
)
++
;
}
return
*
this
;
}
string
&
operator
+=
(
const
string
&
str
){
assert
((
size
+
str
.
size
>
size
)
&&
(
size
+
str
.
size
>
str
.
size
),
"overflow"
);
char
*
new_data
;
uint32_t
new_size
;
if
(
size
>
0
&&
*
(
data
+
size
-
1
)
==
'\0'
)
{
// Null terminated string, remove the \0 when concatenates
new_size
=
size
-
1
+
str
.
size
;
new_data
=
(
char
*
)
malloc
(
new_size
*
sizeof
(
char
));
memcpy
(
new_data
,
data
,
(
size
-
1
)
*
sizeof
(
char
));
memcpy
(
new_data
+
size
-
1
,
str
.
data
,
str
.
size
*
sizeof
(
char
));
}
else
{
new_size
=
size
+
str
.
size
;
new_data
=
(
char
*
)
malloc
(
new_size
*
sizeof
(
char
));
memcpy
(
new_data
,
data
,
size
*
sizeof
(
char
));
memcpy
(
new_data
+
size
,
str
.
data
,
str
.
size
*
sizeof
(
char
));
}
// Release old data
release_data_if_needed
();
// Assign new data
data
=
new_data
;
size
=
new_size
;
own_memory
=
true
;
refcount
=
(
uint32_t
*
)
malloc
(
sizeof
(
uint32_t
));
*
refcount
=
1
;
return
*
this
;
}
// Compare two strings
// Return an integral value indicating the relationship between strings
// >0 if the first string is greater than the second string
// 0 if both strings are equal
// <0 if the first string is smaller than the second string
// The return value also represents the difference between the first character that doesn't match of the two strings
int32_t
compare
(
const
string
&
str
)
const
{
int32_t
result
;
if
(
size
==
str
.
size
)
{
result
=
memcmp
(
data
,
str
.
data
,
size
);
}
else
if
(
size
<
str
.
size
)
{
result
=
memcmp
(
data
,
str
.
data
,
size
);
if
(
result
==
0
)
{
// String is equal up to size of the shorter string, return the difference in byte of the next character
result
=
0
-
(
unsigned
char
)
str
.
data
[
size
];
}
}
else
if
(
size
>
str
.
size
)
{
result
=
memcmp
(
data
,
str
.
data
,
str
.
size
);
if
(
result
==
0
)
{
// String is equal up to size of the shorter string, return the difference in byte of the next character
result
=
(
unsigned
char
)
data
[
str
.
size
];
}
}
return
result
;
}
friend
bool
operator
<
(
const
string
&
lhs
,
const
string
&
rhs
)
{
return
lhs
.
compare
(
rhs
)
<
0
;
}
friend
bool
operator
>
(
const
string
&
lhs
,
const
string
&
rhs
)
{
return
lhs
.
compare
(
rhs
)
>
0
;
}
friend
bool
operator
==
(
const
string
&
lhs
,
const
string
&
rhs
)
{
return
lhs
.
compare
(
rhs
)
==
0
;
}
friend
bool
operator
!=
(
const
string
&
lhs
,
const
string
&
rhs
)
{
return
lhs
.
compare
(
rhs
)
!=
0
;
}
friend
string
operator
+
(
string
lhs
,
const
string
&
rhs
)
{
return
lhs
+=
rhs
;
}
void
print
()
const
{
if
(
size
>
0
&&
*
(
data
+
size
-
1
)
==
'\0'
)
{
// Null terminated string
prints
(
data
);
}
else
{
// Non null terminated string
// We need to specify the size of string so it knows where to stop
prints_l
(
data
,
size
);
}
}
};
}
contracts/test_api/test_api.cpp
浏览文件 @
f21c658b
...
...
@@ -77,10 +77,29 @@ extern "C" {
WASM_TEST_HANDLER
(
test_transaction
,
send_transaction_empty
);
WASM_TEST_HANDLER
(
test_transaction
,
send_transaction_max
);
WASM_TEST_HANDLER
(
test_transaction
,
send_transaction_large
);
//test chain
WASM_TEST_HANDLER
(
test_chain
,
test_activeprods
);
// test string
WASM_TEST_HANDLER
(
test_string
,
construct_with_size
);
WASM_TEST_HANDLER
(
test_string
,
construct_with_data
);
WASM_TEST_HANDLER
(
test_string
,
construct_with_data_copied
);
WASM_TEST_HANDLER
(
test_string
,
construct_with_data_partially
);
WASM_TEST_HANDLER
(
test_string
,
copy_constructor
);
WASM_TEST_HANDLER
(
test_string
,
assignment_operator
);
WASM_TEST_HANDLER
(
test_string
,
index_operator
);
WASM_TEST_HANDLER
(
test_string
,
index_out_of_bound
);
WASM_TEST_HANDLER
(
test_string
,
substring
);
WASM_TEST_HANDLER
(
test_string
,
substring_out_of_bound
);
WASM_TEST_HANDLER
(
test_string
,
concatenation_null_terminated
);
WASM_TEST_HANDLER
(
test_string
,
concatenation_non_null_terminated
);
WASM_TEST_HANDLER
(
test_string
,
assign
);
WASM_TEST_HANDLER
(
test_string
,
comparison_operator
);
WASM_TEST_HANDLER
(
test_string
,
print_null_terminated
);
WASM_TEST_HANDLER
(
test_string
,
print_non_null_terminated
);
WASM_TEST_HANDLER
(
test_string
,
print_unicode
);
//unhandled test call
WASM_TEST_ERROR_CODE
=
WASM_TEST_FAIL
;
}
...
...
contracts/test_api/test_api.hpp
浏览文件 @
f21c658b
...
...
@@ -128,3 +128,23 @@ struct test_transaction {
struct
test_chain
{
static
unsigned
int
test_activeprods
();
};
struct
test_string
{
static
unsigned
int
construct_with_size
();
static
unsigned
int
construct_with_data
();
static
unsigned
int
construct_with_data_copied
();
static
unsigned
int
construct_with_data_partially
();
static
unsigned
int
copy_constructor
();
static
unsigned
int
assignment_operator
();
static
unsigned
int
index_operator
();
static
unsigned
int
index_out_of_bound
();
static
unsigned
int
substring
();
static
unsigned
int
substring_out_of_bound
();
static
unsigned
int
concatenation_null_terminated
();
static
unsigned
int
concatenation_non_null_terminated
();
static
unsigned
int
assign
();
static
unsigned
int
comparison_operator
();
static
unsigned
int
print_null_terminated
();
static
unsigned
int
print_non_null_terminated
();
static
unsigned
int
print_unicode
();
};
contracts/test_api/test_string.cpp
0 → 100644
浏览文件 @
f21c658b
#include <eoslib/string.hpp>
#include <eoslib/eos.hpp>
#include "test_api.hpp"
unsigned
int
test_string
::
construct_with_size
()
{
uint32_t
size
=
100
;
eos
::
string
str
(
size
);
WASM_ASSERT
(
str
.
get_size
()
==
size
,
"str.get_size() == size"
);
return
WASM_TEST_PASS
;
}
unsigned
int
test_string
::
construct_with_data
()
{
char
data
[]
=
"abcdefghij"
;
uint32_t
size
=
sizeof
(
data
)
/
sizeof
(
char
);
eos
::
string
str
(
data
,
size
,
false
);
WASM_ASSERT
(
str
.
get_size
()
==
size
,
"str.get_size() == size"
);
WASM_ASSERT
(
str
.
get_data
()
==
data
,
"str.get_data() == data"
);
WASM_ASSERT
(
str
.
is_own_memory
()
==
false
,
"str.is_own_memory() == false"
);
return
WASM_TEST_PASS
;
}
unsigned
int
test_string
::
construct_with_data_partially
()
{
char
data
[]
=
"abcdefghij"
;
uint32_t
substr_size
=
5
;
uint32_t
offset
=
2
;
eos
::
string
str
(
data
+
offset
,
substr_size
,
false
);
WASM_ASSERT
(
str
.
get_size
()
==
substr_size
,
"str.get_size() == substr_size"
);
WASM_ASSERT
(
str
.
get_data
()
==
data
+
offset
,
"str.get_data() == data + offset"
);
for
(
uint8_t
i
=
offset
;
i
<
substr_size
;
i
++
)
{
WASM_ASSERT
(
str
[
i
]
==
data
[
offset
+
i
],
"str[i] == data[offset + i]"
);
}
WASM_ASSERT
(
str
.
is_own_memory
()
==
false
,
"str.is_own_memory() == false"
);
return
WASM_TEST_PASS
;
}
unsigned
int
test_string
::
construct_with_data_copied
()
{
char
data
[]
=
"abcdefghij"
;
uint32_t
size
=
sizeof
(
data
)
/
sizeof
(
char
);
eos
::
string
str
(
data
,
size
,
true
);
WASM_ASSERT
(
str
.
get_size
()
==
size
,
"str.get_size() == size"
);
WASM_ASSERT
(
str
.
get_data
()
!=
data
,
"str.get_data() != data"
);
for
(
uint8_t
i
=
0
;
i
<
size
;
i
++
)
{
WASM_ASSERT
(
str
[
i
]
==
data
[
i
],
"str[i] == data[i]"
);
}
WASM_ASSERT
(
str
.
is_own_memory
()
==
true
,
"str.is_own_memory() == true"
);
return
WASM_TEST_PASS
;
}
unsigned
int
test_string
::
copy_constructor
()
{
char
data
[]
=
"abcdefghij"
;
uint32_t
size
=
sizeof
(
data
)
/
sizeof
(
char
);
eos
::
string
str1
(
data
,
size
,
true
);
eos
::
string
str2
=
str1
;
WASM_ASSERT
(
str1
.
get_size
()
==
str2
.
get_size
(),
"str1.get_size() == str2.get_size()"
);
WASM_ASSERT
(
str1
.
get_data
()
==
str2
.
get_data
(),
"str1.get_data() == str2.getget_data_size()"
);
WASM_ASSERT
(
str1
.
is_own_memory
()
==
str2
.
is_own_memory
(),
"str1.is_own_memory() == str2.is_own_memory()"
);
WASM_ASSERT
(
str1
.
get_refcount
()
==
str2
.
get_refcount
(),
"str1.get_refcount() == str2.get_refcount()"
);
WASM_ASSERT
(
str1
.
get_refcount
()
==
2
,
"str1.refcount() == 2"
);
return
WASM_TEST_PASS
;
}
unsigned
int
test_string
::
assignment_operator
()
{
char
data
[]
=
"abcdefghij"
;
uint32_t
size
=
sizeof
(
data
)
/
sizeof
(
char
);
eos
::
string
str1
(
data
,
size
,
true
);
eos
::
string
str2
;
str2
=
str1
;
WASM_ASSERT
(
str1
.
get_size
()
==
str2
.
get_size
(),
"str1.get_size() == str2.get_size()"
);
WASM_ASSERT
(
str1
.
get_data
()
==
str2
.
get_data
(),
"str1.get_data() == str2.getget_data_size()"
);
WASM_ASSERT
(
str1
.
is_own_memory
()
==
str2
.
is_own_memory
(),
"str1.is_own_memory() == str2.is_own_memory()"
);
WASM_ASSERT
(
str1
.
get_refcount
()
==
str2
.
get_refcount
(),
"str1.get_refcount() == str2.get_refcount()"
);
WASM_ASSERT
(
str1
.
get_refcount
()
==
2
,
"str1.refcount() == 2"
);
return
WASM_TEST_PASS
;
}
unsigned
int
test_string
::
index_operator
()
{
char
data
[]
=
"abcdefghij"
;
uint32_t
size
=
sizeof
(
data
)
/
sizeof
(
char
);
eos
::
string
str
(
data
,
size
,
false
);
for
(
uint8_t
i
=
0
;
i
<
size
;
i
++
)
{
WASM_ASSERT
(
str
[
i
]
==
data
[
i
],
"str[i] == data[i]"
);
}
return
WASM_TEST_PASS
;
}
unsigned
int
test_string
::
index_out_of_bound
()
{
char
data
[]
=
"abcdefghij"
;
uint32_t
size
=
sizeof
(
data
)
/
sizeof
(
char
);
eos
::
string
str
(
data
,
size
,
false
);
char
c
=
str
[
size
];
return
WASM_TEST_PASS
;
}
unsigned
int
test_string
::
substring
()
{
char
data
[]
=
"abcdefghij"
;
uint32_t
size
=
sizeof
(
data
)
/
sizeof
(
char
);
eos
::
string
str
(
data
,
size
,
false
);
uint32_t
substr_size
=
5
;
uint32_t
offset
=
2
;
eos
::
string
substr
=
str
.
substr
(
offset
,
substr_size
,
false
);
WASM_ASSERT
(
substr
.
get_size
()
==
substr_size
,
"str.get_size() == substr_size"
);
WASM_ASSERT
(
substr
.
get_data
()
==
str
.
get_data
()
+
offset
,
"substr.get_data() == str.get_data() + offset"
);
for
(
uint8_t
i
=
offset
;
i
<
substr_size
;
i
++
)
{
WASM_ASSERT
(
substr
[
i
]
==
str
[
offset
+
i
],
"substr[i] == str[offset + i]"
);
}
WASM_ASSERT
(
substr
.
is_own_memory
()
==
false
,
"substr.is_own_memory() == false"
);
return
WASM_TEST_PASS
;
}
unsigned
int
test_string
::
substring_out_of_bound
()
{
char
data
[]
=
"abcdefghij"
;
uint32_t
size
=
sizeof
(
data
)
/
sizeof
(
char
);
eos
::
string
str
(
data
,
size
,
false
);
uint32_t
substr_size
=
size
;
uint32_t
offset
=
1
;
eos
::
string
substr
=
str
.
substr
(
offset
,
substr_size
,
false
);
return
WASM_TEST_PASS
;
}
unsigned
int
test_string
::
concatenation_null_terminated
()
{
char
data1
[]
=
"abcdefghij"
;
uint32_t
size1
=
sizeof
(
data1
)
/
sizeof
(
char
);
eos
::
string
str1
(
data1
,
size1
,
false
);
char
data2
[]
=
"klmnoppqrst"
;
uint32_t
size2
=
sizeof
(
data2
)
/
sizeof
(
char
);
eos
::
string
str2
(
data2
,
size2
,
false
);
str1
+=
str2
;
WASM_ASSERT
(
str1
.
get_data
()
!=
data1
,
"str1.get_data() != data1"
);
WASM_ASSERT
(
str1
.
get_size
()
==
size1
+
size2
-
1
,
"str1.get_size == size1 + size2 - 1"
);
for
(
uint8_t
i
=
0
;
i
<
size1
-
1
;
i
++
)
{
WASM_ASSERT
(
str1
[
i
]
==
data1
[
i
],
"str1[i] == data1[i]"
);
}
for
(
uint8_t
i
=
0
;
i
<
size2
;
i
++
)
{
WASM_ASSERT
(
str1
[
size1
-
1
+
i
]
==
data2
[
i
],
"str1[i] == data2[i]"
);
}
return
WASM_TEST_PASS
;
}
unsigned
int
test_string
::
concatenation_non_null_terminated
()
{
char
data1
[]
=
{
'a'
,
'b'
,
'c'
,
'd'
,
'e'
,
'f'
,
'g'
,
'h'
,
'i'
,
'j'
};
uint32_t
size1
=
sizeof
(
data1
)
/
sizeof
(
char
);
eos
::
string
str1
(
data1
,
size1
,
false
);
char
data2
[]
=
{
'k'
,
'l'
,
'm'
,
'n'
,
'o'
,
'p'
,
'q'
,
'r'
,
's'
,
't'
};
uint32_t
size2
=
sizeof
(
data2
)
/
sizeof
(
char
);
eos
::
string
str2
(
data2
,
size2
,
false
);
str1
+=
str2
;
WASM_ASSERT
(
str1
.
get_data
()
!=
data1
,
"str1.get_data() != data1"
);
WASM_ASSERT
(
str1
.
get_size
()
==
size1
+
size2
,
"str1.get_size == size1 + size2"
);
for
(
uint8_t
i
=
0
;
i
<
size1
;
i
++
)
{
WASM_ASSERT
(
str1
[
i
]
==
data1
[
i
],
"str1[i] == data1[i]"
);
}
for
(
uint8_t
i
=
0
;
i
<
size2
;
i
++
)
{
WASM_ASSERT
(
str1
[
size1
+
i
]
==
data2
[
i
],
"str1[i] == data2[i]"
);
}
return
WASM_TEST_PASS
;
}
unsigned
int
test_string
::
assign
()
{
char
data
[]
=
"abcdefghij"
;
uint32_t
size
=
sizeof
(
data
)
/
sizeof
(
char
);
eos
::
string
str
(
100
);
str
.
assign
(
data
,
size
,
true
);
WASM_ASSERT
(
str
.
get_size
()
==
size
,
"str.get_size() == size"
);
WASM_ASSERT
(
str
.
get_data
()
!=
data
,
"str.get_data() != data"
);
for
(
uint8_t
i
=
0
;
i
<
size
;
i
++
)
{
WASM_ASSERT
(
str
[
i
]
==
data
[
i
],
"str[i] == data[i]"
);
}
WASM_ASSERT
(
str
.
is_own_memory
()
==
true
,
"str.is_own_memory() == true"
);
return
WASM_TEST_PASS
;
}
unsigned
int
test_string
::
comparison_operator
()
{
char
data1
[]
=
"abcdefghij"
;
uint32_t
size1
=
sizeof
(
data1
)
/
sizeof
(
char
);
eos
::
string
str1
(
data1
,
size1
,
false
);
char
data2
[]
=
"abcdefghij"
;
uint32_t
size2
=
sizeof
(
data2
)
/
sizeof
(
char
);
eos
::
string
str2
(
data2
,
size2
,
false
);
char
data3
[]
=
"klmno"
;
uint32_t
size3
=
sizeof
(
data3
)
/
sizeof
(
char
);
eos
::
string
str3
(
data3
,
size3
,
false
);
char
data4
[]
=
"aaaaaaaaaaaaaaa"
;
uint32_t
size4
=
sizeof
(
data4
)
/
sizeof
(
char
);
eos
::
string
str4
(
data4
,
size4
,
false
);
char
data5
[]
=
"你好"
;
uint32_t
size5
=
sizeof
(
data5
)
/
sizeof
(
char
);
eos
::
string
str5
(
data5
,
size5
,
false
);
char
data6
[]
=
"你好嗎?"
;
uint32_t
size6
=
sizeof
(
data6
)
/
sizeof
(
char
);
eos
::
string
str6
(
data6
,
size6
,
false
);
char
data7
[]
=
{
'a'
,
'b'
,
'c'
,
'd'
,
'e'
};
uint32_t
size7
=
sizeof
(
data7
)
/
sizeof
(
char
);
eos
::
string
str7
(
data7
,
size7
,
false
);
char
data8
[]
=
{
'a'
,
'b'
,
'c'
};
uint32_t
size8
=
sizeof
(
data8
)
/
sizeof
(
char
);
eos
::
string
str8
(
data8
,
size8
,
false
);
WASM_ASSERT
(
str1
==
str2
,
"str1 == str2"
);
WASM_ASSERT
(
str1
!=
str3
,
"str1 != str3"
);
WASM_ASSERT
(
str1
<
str3
,
"str1 < str3"
);
WASM_ASSERT
(
str2
>
str4
,
"str2 > str4"
);
WASM_ASSERT
(
str1
.
compare
(
str2
)
==
0
,
"str1.compare(str2) == 0"
);
WASM_ASSERT
(
str1
.
compare
(
str3
)
<
0
,
"str1.compare(str3) < 0"
);
WASM_ASSERT
(
str1
.
compare
(
str4
)
>
0
,
"str1.compare(str4) > 0"
);
WASM_ASSERT
(
str5
.
compare
(
str6
)
<
0
,
"st5.compare(str6) < 0"
);
WASM_ASSERT
(
str7
.
compare
(
str8
)
>
0
,
"str7.compare(str8) > 0"
);
return
WASM_TEST_PASS
;
}
unsigned
int
test_string
::
print_null_terminated
()
{
char
data
[]
=
"Hello World!"
;
uint32_t
size
=
sizeof
(
data
)
/
sizeof
(
char
);
eos
::
string
str
(
data
,
size
,
false
);
eos
::
print
(
str
);
return
WASM_TEST_PASS
;
}
unsigned
int
test_string
::
print_non_null_terminated
()
{
char
data
[]
=
{
'H'
,
'e'
,
'l'
,
'l'
,
'o'
,
' '
,
'W'
,
'o'
,
'r'
,
'l'
,
'd'
,
'!'
};
uint32_t
size
=
sizeof
(
data
)
/
sizeof
(
char
);
eos
::
string
str
(
data
,
size
,
false
);
eos
::
print
(
str
);
return
WASM_TEST_PASS
;
}
unsigned
int
test_string
::
print_unicode
()
{
char
data
[]
=
"你好,世界!"
;
uint32_t
size
=
sizeof
(
data
)
/
sizeof
(
char
);
eos
::
string
str
(
data
,
size
,
false
);
eos
::
print
(
str
);
return
WASM_TEST_PASS
;
}
libraries/chain/wasm_interface.cpp
浏览文件 @
f21c658b
...
...
@@ -338,6 +338,17 @@ DEFINE_INTRINSIC_FUNCTION3(env,memcpy,memcpy,i32,i32,dstp,i32,srcp,i32,len) {
return
dstp
;
}
DEFINE_INTRINSIC_FUNCTION3
(
env
,
memcmp
,
memcmp
,
i32
,
i32
,
dstp
,
i32
,
srcp
,
i32
,
len
)
{
auto
&
wasm
=
wasm_interface
::
get
();
auto
mem
=
wasm
.
current_memory
;
char
*
dst
=
memoryArrayPtr
<
char
>
(
mem
,
dstp
,
len
);
const
char
*
src
=
memoryArrayPtr
<
const
char
>
(
mem
,
srcp
,
len
);
FC_ASSERT
(
len
>
0
);
return
memcmp
(
dst
,
src
,
uint32_t
(
len
)
);
}
DEFINE_INTRINSIC_FUNCTION3
(
env
,
memset
,
memset
,
i32
,
i32
,
rel_ptr
,
i32
,
value
,
i32
,
len
)
{
auto
&
wasm
=
wasm_interface
::
get
();
auto
mem
=
wasm
.
current_memory
;
...
...
@@ -525,10 +536,19 @@ DEFINE_INTRINSIC_FUNCTION1(env,prints,prints,none,i32,charptr) {
std
::
cerr
<<
std
::
string
(
str
,
strnlen
(
str
,
wasm
.
current_state
->
mem_end
-
charptr
)
);
}
DEFINE_INTRINSIC_FUNCTION2
(
env
,
prints_l
,
prints_l
,
none
,
i32
,
charptr
,
i32
,
len
)
{
auto
&
wasm
=
wasm_interface
::
get
();
auto
mem
=
wasm
.
current_memory
;
const
char
*
str
=
&
memoryRef
<
const
char
>
(
mem
,
charptr
);
std
::
cerr
<<
std
::
string
(
str
,
len
);
}
DEFINE_INTRINSIC_FUNCTION2
(
env
,
printhex
,
printhex
,
none
,
i32
,
data
,
i32
,
datalen
)
{
auto
&
wasm
=
wasm_interface
::
get
();
auto
mem
=
wasm
.
current_memory
;
char
*
buff
=
memoryArrayPtr
<
char
>
(
mem
,
data
,
datalen
);
std
::
cerr
<<
fc
::
to_hex
(
buff
,
datalen
)
<<
std
::
endl
;
}
...
...
tests/api_tests/api_tests.cpp
浏览文件 @
f21c658b
...
...
@@ -430,6 +430,30 @@ BOOST_FIXTURE_TEST_CASE(test_all, testing_fixture)
std
::
copy
(
gpo
.
active_producers
.
begin
(),
gpo
.
active_producers
.
end
(),
prods
.
begin
());
BOOST_CHECK_MESSAGE
(
CALL_TEST_FUNCTION
(
TEST_METHOD
(
"test_chain"
,
"test_activeprods"
),
{},
fc
::
raw
::
pack
(
prods
)
)
==
WASM_TEST_PASS
,
"test_chain::test_activeprods()"
);
// Test string
BOOST_CHECK_MESSAGE
(
CALL_TEST_FUNCTION
(
TEST_METHOD
(
"test_string"
,
"construct_with_size"
),
{},
{}
)
==
WASM_TEST_PASS
,
"test_string::construct_with_size()"
);
BOOST_CHECK_MESSAGE
(
CALL_TEST_FUNCTION
(
TEST_METHOD
(
"test_string"
,
"construct_with_data"
),
{},
{}
)
==
WASM_TEST_PASS
,
"test_string::construct_with_data()"
);
BOOST_CHECK_MESSAGE
(
CALL_TEST_FUNCTION
(
TEST_METHOD
(
"test_string"
,
"construct_with_data_copied"
),
{},
{}
)
==
WASM_TEST_PASS
,
"test_string::construct_with_data_copied()"
);
BOOST_CHECK_MESSAGE
(
CALL_TEST_FUNCTION
(
TEST_METHOD
(
"test_string"
,
"construct_with_data_partially"
),
{},
{}
)
==
WASM_TEST_PASS
,
"test_string::construct_with_data_partially()"
);
BOOST_CHECK_MESSAGE
(
CALL_TEST_FUNCTION
(
TEST_METHOD
(
"test_string"
,
"copy_constructor"
),
{},
{}
)
==
WASM_TEST_PASS
,
"test_string::copy_constructor()"
);
BOOST_CHECK_MESSAGE
(
CALL_TEST_FUNCTION
(
TEST_METHOD
(
"test_string"
,
"assignment_operator"
),
{},
{}
)
==
WASM_TEST_PASS
,
"test_string::assignment_operator()"
);
BOOST_CHECK_MESSAGE
(
CALL_TEST_FUNCTION
(
TEST_METHOD
(
"test_string"
,
"index_operator"
),
{},
{}
)
==
WASM_TEST_PASS
,
"test_string::index_operator()"
);
BOOST_CHECK_EXCEPTION
(
CALL_TEST_FUNCTION
(
TEST_METHOD
(
"test_string"
,
"index_out_of_bound"
),
{},
{}
),
fc
::
assert_exception
,
is_assert_exception
);
BOOST_CHECK_MESSAGE
(
CALL_TEST_FUNCTION
(
TEST_METHOD
(
"test_string"
,
"substring"
),
{},
{}
)
==
WASM_TEST_PASS
,
"test_string::substring()"
);
BOOST_CHECK_EXCEPTION
(
CALL_TEST_FUNCTION
(
TEST_METHOD
(
"test_string"
,
"substring_out_of_bound"
),
{},
{}
),
fc
::
assert_exception
,
is_assert_exception
);
BOOST_CHECK_MESSAGE
(
CALL_TEST_FUNCTION
(
TEST_METHOD
(
"test_string"
,
"concatenation_null_terminated"
),
{},
{}
)
==
WASM_TEST_PASS
,
"test_string::concatenation_null_terminated()"
);
BOOST_CHECK_MESSAGE
(
CALL_TEST_FUNCTION
(
TEST_METHOD
(
"test_string"
,
"concatenation_non_null_terminated"
),
{},
{}
)
==
WASM_TEST_PASS
,
"test_string::concatenation_non_null_terminated()"
);
BOOST_CHECK_MESSAGE
(
CALL_TEST_FUNCTION
(
TEST_METHOD
(
"test_string"
,
"assign"
),
{},
{}
)
==
WASM_TEST_PASS
,
"test_string::assign()"
);
BOOST_CHECK_MESSAGE
(
CALL_TEST_FUNCTION
(
TEST_METHOD
(
"test_string"
,
"comparison_operator"
),
{},
{}
)
==
WASM_TEST_PASS
,
"test_string::comparison_operator()"
);
CAPTURE
(
cerr
,
CALL_TEST_FUNCTION
(
TEST_METHOD
(
"test_string"
,
"print_null_terminated"
),
{},
{})
);
BOOST_CHECK_EQUAL
(
capture
.
size
()
,
1
);
BOOST_CHECK_EQUAL
(
capture
[
0
],
"Hello World!"
);
CAPTURE
(
cerr
,
CALL_TEST_FUNCTION
(
TEST_METHOD
(
"test_string"
,
"print_non_null_terminated"
),
{},
{})
);
BOOST_CHECK_EQUAL
(
capture
.
size
()
,
1
);
BOOST_CHECK_EQUAL
(
capture
[
0
],
"Hello World!"
);
CAPTURE
(
cerr
,
CALL_TEST_FUNCTION
(
TEST_METHOD
(
"test_string"
,
"print_unicode"
),
{},
{})
);
BOOST_CHECK_EQUAL
(
capture
.
size
()
,
1
);
BOOST_CHECK_EQUAL
(
capture
[
0
],
"你好,世界!"
);
}
FC_LOG_AND_RETHROW
()
}
...
...
@@ -482,6 +506,9 @@ BOOST_FIXTURE_TEST_CASE(test_case_name, testing_fixture)
//Test wasm memory allocation
MEMORY_TEST_CASE
(
test_memory
,
testmemory
,
memory_test_wast
)
//Test memcmp
MEMORY_TEST_CASE
(
test_memcmp
,
testmemcmp
,
memory_test_wast
)
//Test wasm memory allocation at boundaries
MEMORY_TEST_CASE
(
test_memory_bounds
,
testbounds
,
memory_test_wast
)
...
...
tests/api_tests/memory_test/memory_test.cpp
浏览文件 @
f21c658b
...
...
@@ -168,6 +168,24 @@ extern "C" {
memcpy
(
buf3
,
&
buf3
[
49
],
50
);
}
void
test_memcmp
()
{
char
buf1
[]
=
"abcde"
;
char
buf2
[]
=
"abcde"
;
int32_t
res1
=
memcmp
(
buf1
,
buf2
,
6
);
assert
(
res1
==
0
,
"first data should be equal to second data"
);
char
buf3
[]
=
"abcde"
;
char
buf4
[]
=
"fghij"
;
int32_t
res2
=
memcmp
(
buf3
,
buf4
,
6
);
assert
(
res2
<
0
,
"first data should be smaller than second data"
);
char
buf5
[]
=
"fghij"
;
char
buf6
[]
=
"abcde"
;
int32_t
res3
=
memcmp
(
buf5
,
buf6
,
6
);
assert
(
res3
>
0
,
"first data should be larger than second data"
);
}
/// The apply method implements the dispatch of events to this contract
void
apply
(
uint64_t
code
,
uint64_t
action
)
{
...
...
@@ -206,5 +224,12 @@ extern "C" {
test_memcpy_overlap_end
();
}
}
else
if
(
code
==
N
(
testmemcmp
)
)
{
if
(
action
==
N
(
transfer
)
)
{
test_memcmp
();
}
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录