Fabcoin Core  0.16.2
P2P Digital Currency
createRandomTest.cpp
Go to the documentation of this file.
1 /*
2  This file is part of cpp-ethereum.
3 
4  cpp-ethereum is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  cpp-ethereum is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
16 */
22 #include <string>
23 #include <iostream>
24 
25 #include <libdevcore/CommonData.h>
28 #include <libevm/VMFactory.h>
29 #include <libdevcore/Common.h>
30 
31 //String Variables
32 extern std::string const c_testExampleStateTest;
33 extern std::string const c_testExampleTransactionTest;
34 extern std::string const c_testExampleVMTest;
35 extern std::string const c_testExampleBlockchainTest;
36 extern std::string const c_testExampleRLPTest;
37 
38 //Main Test functinos
39 void fillRandomTest(std::function<void(json_spirit::mValue&, bool)> _doTests, std::string const& _testString, bool _debug = false);
40 int checkRandomTest(std::function<void(json_spirit::mValue&, bool)> _doTests, json_spirit::mValue& _value, bool _debug = false);
41 
42 namespace dev { namespace test {
43 int createRandomTest(std::vector<char*> const& _parameters)
44 {
45  std::string testSuite;
46  std::string testFillString;
47  json_spirit::mValue testmValue;
48  bool checktest = false;
49  bool filldebug = false;
50  bool debug = false;
51  bool filltest = false;
52 
54 
55  testSuite = options.rCurrentTestSuite;
56  if (testSuite != "BlockChainTests" && testSuite != "TransactionTests" && testSuite != "StateTests"
57  && testSuite != "VMTests")
58  testSuite = "";
59 
60  for (size_t i = 0; i < _parameters.size(); ++i)
61  {
62  auto arg = std::string{_parameters.at(i)};
63 
64  if (arg == "--fulloutput")
65  options.fulloutput = true;
66  else
67  if (arg == "--checktest" || arg == "--filltest")
68  {
69  std::string s = options.rCheckTest;
70  BOOST_REQUIRE_MESSAGE(s.length() > 0, "Error! Content of argument is empty! (Usage -checktest textstream)");
71 
72  if (arg == "--filltest")
73  {
74  testFillString = s;
75  filltest = true;
76  }
77  else
78  {
79  if (s.find(".json") != std::string::npos)
80  {
81  boost::filesystem::path p(__FILE__);
82  s = asString(dev::contents(s));
83  }
84  read_string(s, testmValue);
85  checktest = true;
86  }
87  }
88  else
89  if (arg == "--debug")
90  debug = true;
91  else
92  if (arg == "--filldebug")
93  filldebug = true;
94  }
95 
96  if (testSuite == "")
97  {
98  std::cerr << "Error! Test suite not supported! (Usage -t TestSuite)" << std::endl;
99  return 1;
100  }
101  else
102  {
103  if (checktest)
104  std::cout << "Testing: " << testSuite.substr(0, testSuite.length() - 1) << "... ";
105 
106  if (testSuite == "BlockChainTests")
107  {
108  if (checktest)
109  return checkRandomTest(dev::test::doBlockchainTests, testmValue, debug);
110  else
111  fillRandomTest(dev::test::doBlockchainTests, (filltest) ? testFillString : c_testExampleBlockchainTest, filldebug);
112  }
113  else
114  if (testSuite == "TransactionTests")
115  {
116  if (checktest)
117  return checkRandomTest(dev::test::doTransactionTests, testmValue, debug);
118  else
119  fillRandomTest(dev::test::doTransactionTests, (filltest) ? testFillString : c_testExampleTransactionTest, filldebug);
120  }
121  else
122  if (testSuite == "VMTests")
123  {
124  if (checktest)
125  {
127  return checkRandomTest(dev::test::doVMTests, testmValue, debug);
128  }
129  else
130  fillRandomTest(dev::test::doVMTests, (filltest) ? testFillString : c_testExampleVMTest, filldebug);
131  }
132  }
133 
134  return 0;
135 }
136 }} //namespaces
137 
138 int checkRandomTest(std::function<void(json_spirit::mValue&, bool)> _doTests, json_spirit::mValue& _value, bool _debug)
139 {
140  bool ret = 0;
141  try
142  {
143  //redirect all output to the stream
144  std::ostringstream strCout;
145  std::streambuf* oldCoutStreamBuf = std::cout.rdbuf();
146  if (!_debug)
147  {
148  std::cout.rdbuf( strCout.rdbuf() );
149  std::cerr.rdbuf( strCout.rdbuf() );
150  }
151 
152  _doTests(_value, false);
153 
154  //restroe output
155  if (!_debug)
156  {
157  std::cout.rdbuf(oldCoutStreamBuf);
158  std::cerr.rdbuf(oldCoutStreamBuf);
159  }
160  }
161  catch (dev::Exception const& _e)
162  {
163  std::cout << "Failed test with Exception: " << diagnostic_information(_e) << std::endl;
164  ret = 1;
165  }
166  catch (std::exception const& _e)
167  {
168  std::cout << "Failed test with Exception: " << _e.what() << std::endl;
169  ret = 1;
170  }
171  return ret;
172 }
173 
174 void fillRandomTest(std::function<void(json_spirit::mValue&, bool)> _doTests, std::string const& _testString, bool _debug)
175 {
176  //redirect all output to the stream
177  std::ostringstream strCout;
178  std::streambuf* oldCoutStreamBuf = std::cout.rdbuf();
179  if (!_debug)
180  {
181  std::cout.rdbuf( strCout.rdbuf() );
182  std::cerr.rdbuf( strCout.rdbuf() );
183  }
184 
186  try
187  {
188  std::string newTest = _testString;
189  std::map<std::string, std::string> nullReplaceMap;
190  dev::test::RandomCode::parseTestWithTypes(newTest, nullReplaceMap);
191  json_spirit::read_string(newTest, v);
192  _doTests(v, true);
193  }
194  catch(...)
195  {
196  std::cerr << "Test fill exception!";
197  }
198 
199  //restroe output
200  if (!_debug)
201  {
202  std::cout.rdbuf(oldCoutStreamBuf);
203  std::cerr.rdbuf(oldCoutStreamBuf);
204  }
205  std::cout << json_spirit::write_string(v, true);
206 }
207 
209 void dev::test::RandomCode::parseTestWithTypes(std::string& _test, std::map<std::string, std::string> const& _varMap)
210 {
212  options.setWeight(dev::eth::Instruction::STOP, 10); //default 50
216  options.addAddress(dev::Address("0xffffffffffffffffffffffffffffffffffffffff"));
217  options.addAddress(dev::Address("0x1000000000000000000000000000000000000000"));
218  options.addAddress(dev::Address("0x095e7baea6a6c7c4c2dfeb977efac326af552d87"));
219  options.addAddress(dev::Address("0x945304eb96065b2a98b57a48a06ae28d285a71b5"));
220  options.addAddress(dev::Address("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"));
221  options.addAddress(dev::Address("0x0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6"));
222  options.addAddress(dev::Address("0x0000000000000000000000000000000000000001"));
223  options.addAddress(dev::Address("0x0000000000000000000000000000000000000002"));
224  options.addAddress(dev::Address("0x0000000000000000000000000000000000000003"));
225  options.addAddress(dev::Address("0x0000000000000000000000000000000000000004"));
226  options.smartCodeProbability = 60;
227 
228  std::vector<std::string> types = getTypes();
229 
230  for (std::map<std::string, std::string>::const_iterator it = _varMap.begin(); it != _varMap.end(); it++)
231  types.push_back(it->first);
232 
233  for (unsigned i = 0; i < types.size(); i++)
234  {
235  std::size_t pos = _test.find(types.at(i));
236  while (pos != std::string::npos)
237  {
238  if (types.at(i) == "[RLP]")
239  {
240  std::string debug;
241  int randomDepth = 1 + (int)dev::test::RandomCode::randomUniInt() % 10;
242  _test.replace(pos, 5, dev::test::RandomCode::rndRLPSequence(randomDepth, debug));
243  cnote << debug;
244  }
245  else
246  if (types.at(i) == "[CODE]")
247  _test.replace(pos, 6, "0x"+dev::test::RandomCode::generate(10, options));
248  else
249  if (types.at(i) == "[HEX]")
250  _test.replace(pos, 5, dev::test::RandomCode::randomUniIntHex());
251  else
252  if (types.at(i) == "[HEX32]")
254  else
255  if (types.at(i) == "[GASLIMIT]")
256  _test.replace(pos, 10, dev::test::RandomCode::randomUniIntHex(dev::u256("3000000000")));
257  else
258  if (types.at(i) == "[HASH20]")
259  _test.replace(pos, 8, dev::test::RandomCode::rndByteSequence(20));
260  else
261  if (types.at(i) == "[0xHASH32]")
262  _test.replace(pos, 10, "0x" + dev::test::RandomCode::rndByteSequence(32));
263  else
264  if (types.at(i) == "[HASH32]")
265  _test.replace(pos, 8, dev::test::RandomCode::rndByteSequence(32));
266  else
267  if (types.at(i) == "[V]")
268  {
269  int random = (int)dev::test::RandomCode::randomUniInt() % 100;
270  if (random < 30)
271  _test.replace(pos, 3, "0x1c");
272  else
273  if (random < 60)
274  _test.replace(pos, 3, "0x1d");
275  else
276  _test.replace(pos, 3, "0x" + dev::test::RandomCode::rndByteSequence(1));
277  }
278  else
279  _test.replace(pos, types.at(i).size(), _varMap.at(types.at(i)));
280 
281  pos = _test.find(types.at(i));
282  }
283  }
284 }
285 
286 std::vector<std::string> dev::test::RandomCode::getTypes()
287 {
288  return {"[RLP]", "[CODE]", "[HEX]", "[HEX32]", "[HASH20]", "[HASH32]", "[0xHASH32]", "[V]", "[GASLIMIT]"};
289 }
290 
291 std::string const c_testExampleTransactionTest = R"(
292 {
293  "randomTransactionTest" : {
294  "transaction" :
295  {
296  "data" : "[CODE]",
297  "gasLimit" : "[HEX]",
298  "gasPrice" : "[HEX]",
299  "nonce" : "[HEX]",
300  "to" : "[HASH20]",
301  "value" : "[HEX]",
302  "v" : "[V]",
303  "r" : "[0xHASH32]",
304  "s" : "[0xHASH32]"
305  }
306  }
307 }
308 )";
309 
310 std::string const c_testExampleStateTest = R"(
311 {
312  "randomStatetest" : {
313  "env" : {
314  "currentCoinbase" : "[HASH20]",
315  "currentDifficulty" : "[HEX]",
316  "currentGasLimit" : "[GASLIMIT]",
317  "currentNumber" : "[HEX32]",
318  "currentTimestamp" : "[HEX]",
319  "previousHash" : "[HASH32]"
320  },
321  "pre" : {
322  "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
323  "balance" : "[HEX]",
324  "code" : "[CODE]",
325  "nonce" : "[V]",
326  "storage" : {
327  }
328  },
329  "945304eb96065b2a98b57a48a06ae28d285a71b5" : {
330  "balance" : "[HEX]",
331  "code" : "[CODE]",
332  "nonce" : "[V]",
333  "storage" : {
334  }
335  },
336  "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
337  "balance" : "[HEX]",
338  "code" : "0x",
339  "nonce" : "0",
340  "storage" : {
341  }
342  }
343  },
344  "transaction" : {
345  "data" : "[CODE]",
346  "gasLimit" : "[HEX]",
347  "gasPrice" : "[HEX32]",
348  "nonce" : "0",
349  "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
350  "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
351  "value" : "[HEX]"
352  }
353  }
354 }
355 )";
356 
357 std::string const c_testExampleVMTest = R"(
358 {
359  "randomVMTest": {
360  "env" : {
361  "previousHash" : "[HASH32]",
362  "currentNumber" : "[HEX]",
363  "currentGasLimit" : "[GASLIMIT]",
364  "currentDifficulty" : "[HEX]",
365  "currentTimestamp" : "[HEX]",
366  "currentCoinbase" : "[HASH20]"
367  },
368  "pre" : {
369  "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : {
370  "balance" : "[HEX]",
371  "nonce" : "[HEX]",
372  "code" : "[CODE]",
373  "storage": {}
374  }
375  },
376  "exec" : {
377  "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
378  "origin" : "[HASH20]",
379  "caller" : "[HASH20]",
380  "value" : "[HEX]",
381  "data" : "[CODE]",
382  "gasPrice" : "[V]",
383  "gas" : "[HEX]"
384  }
385  }
386 }
387 )";
388 
389 std::string const c_testExampleRLPTest = R"(
390 {
391  "randomRLPTest" : {
392  "out" : "[RLP]"
393  }
394 }
395 )";
396 
397 std::string const c_testExampleBlockchainTest = R"(
398 {
399  "randomBlockTest" : {
400  "genesisBlockHeader" : {
401  "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
402  "coinbase" : "[HASH20]",
403  "difficulty" : "131072",
404  "extraData" : "[CODE]",
405  "gasLimit" : "4712388",
406  "gasUsed" : "0",
407  "mixHash" : "[0xHASH32]",
408  "nonce" : "0x0102030405060708",
409  "number" : "0",
410  "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
411  "receiptTrie" : "[0xHASH32]",
412  "stateRoot" : "[0xHASH32]",
413  "timestamp" : "[HEX]",
414  "transactionsTrie" : "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
415  "uncleHash" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
416  },
417  "pre" : {
418  "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
419  "balance" : "[HEX]",
420  "nonce" : "0",
421  "code" : "",
422  "storage": {}
423  },
424  "095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
425  "balance" : "[HEX]",
426  "nonce" : "0",
427  "code" : "[CODE]",
428  "storage": {}
429  }
430  },
431  "blocks" : [
432  {
433  "transactions" : [
434  {
435  "data" : "[CODE]",
436  "gasLimit" : "[HEX]",
437  "gasPrice" : "[V]",
438  "nonce" : "0",
439  "secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
440  "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
441  "value" : "[V]"
442  }
443  ],
444  "uncleHeaders" : [
445  ]
446  }
447  ]
448  }
449 }
450 )";
std::string const c_testExampleBlockchainTest
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
Definition: Arith256.cpp:15
std::string const c_testExampleTransactionTest
#define function(a, b, c, d, k, s)
static Options const & get(int argc=0, char **argv=0)
Get reference to options The first time used, options are parsed with argc, argv. ...
Definition: Options.cpp:203
static void setKind(VMKind _kind)
Set global VM kind.
Definition: VMFactory.cpp:36
EXPORT void debug(uint64_t a, uint64_t b, uint64_t c, uint64_t d, char z)
Definition: Arith256.cpp:415
static std::vector< std::string > getTypes()
std::string const c_testExampleStateTest
void addAddress(dev::Address const &_address)
Definition: fuzzHelper.cpp:384
std::string rCurrentTestSuite
Remember test suite before boost overwrite (for random tests)
Definition: Options.h:47
bool read_string(const String_type &s, Value_type &value)
Base class for all exceptions.
Definition: Exceptions.h:39
static std::string rndRLPSequence(int _depth, std::string &_debug)
Generate random rlp byte sequence of a given depth (e.g [[[]],[]]).
Definition: fuzzHelper.cpp:182
void doTransactionTests(json_spirit::mValue &_v, bool _fillin)
void setWeight(dev::eth::Instruction _opCode, int _weight)
Definition: fuzzHelper.cpp:378
ExecStats::duration max
Definition: ExecStats.cpp:36
std::string const c_testExampleRLPTest
save word to storage
message-call with another account&#39;s code only
std::string rCheckTest
Test Input (for random tests)
Definition: Options.h:46
static void parseTestWithTypes(std::string &_test, std::map< std::string, std::string > const &_varMap)
Replace keywords in given string with values.
Fixed-size raw-byte array container type, with an API optimised for storing hashes.
Definition: FixedHash.h:47
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void >> u256
Definition: Common.h:125
std::string const c_testExampleVMTest
void fillRandomTest(std::function< void(json_spirit::mValue &, bool)> _doTests, std::string const &_testString, bool _debug=false)
void doVMTests(json_spirit::mValue &_v, bool _fillin)
Definition: vm.cpp:286
int checkRandomTest(std::function< void(json_spirit::mValue &, bool)> _doTests, json_spirit::mValue &_value, bool _debug=false)
std::streambuf * oldCoutStreamBuf
Definition: boostTest.cpp:48
Value_type::String_type write_string(const Value_type &value, bool pretty)
#define cnote
Definition: Log.h:303
static u256 randomUniInt(u256 _maxVal=0)
Definition: fuzzHelper.cpp:259
static std::string rndByteSequence(int _length=1, SizeStrictness _sizeType=SizeStrictness::Strict)
Generate random byte string of a given length.
Definition: fuzzHelper.cpp:191
static std::string randomUniIntHex(u256 _maxVal=0)
Generate random int64.
Definition: fuzzHelper.cpp:248
static std::string generate(int _maxOpNumber=1, RandomCodeOptions _options=RandomCodeOptions())
Generate random vm code.
Definition: fuzzHelper.cpp:205
message-call into an account
void doBlockchainTests(json_spirit::mValue &_v, bool _fillin)
int createRandomTest(std::vector< char * > const &_parameters)
bytes contents(std::string const &_file)
Retrieve and returns the contents of the given file.
bool fulloutput
Replace large output to just it&#39;s length.
Definition: Options.h:49
std::string asString(bytes const &_b)
Converts byte array to a string containing the same (binary) data.
Definition: CommonData.h:79
Helper functions to work with json::spirit and test files.