From 08b4ade2541a58165efa927cf69e51f0eda1e25a Mon Sep 17 00:00:00 2001 From: jzethar Date: Thu, 1 Aug 2024 00:06:40 +0500 Subject: [PATCH 1/3] AutoGenTest module --- 3xpl.php | 231 +++++++++++++++------- CONTRIBUTORS.md | 1 + Engine/AutoGenTest.php | 37 ++++ Engine/DebugHelpers.php | 73 ++++++- Init.php | 1 + Modules/Tests/zkSyncEraMainModuleTest.php | 12 ++ Modules/zkSyncEraMainModule.php | 6 + 7 files changed, 289 insertions(+), 72 deletions(-) create mode 100644 Engine/AutoGenTest.php create mode 100644 Modules/Tests/zkSyncEraMainModuleTest.php diff --git a/3xpl.php b/3xpl.php index f66f3f85..af622ac8 100644 --- a/3xpl.php +++ b/3xpl.php @@ -105,6 +105,7 @@ ', Address extras ' . cli_format_reverse('') . ', Currency supply ' . cli_format_reverse('') . ', Broadcast transaction ' . cli_format_reverse('') . + ', Automatic test generation ' . cli_format_reverse('') . N; if (isset($argv[2])) @@ -119,7 +120,7 @@ $input_argv[] = $chosen_option; -if (!in_array($chosen_option, ['L', 'B', 'PB', 'PR', 'M', 'H', 'T', 'AT', 'AA', 'CS', 'BT'])) +if (!in_array($chosen_option, ['L', 'B', 'PB', 'PR', 'M', 'H', 'T', 'AT', 'AA', 'CS', 'BT', 'AG'])) die(cli_format_error('Wrong choice for 2nd param') . N); echo N; @@ -226,72 +227,7 @@ } elseif ($filter === 'D') { - // TSV format: blockchain module block transaction sort_key time - // address currency sign effect valid extra ?extra_indexed - - $tsv_fields = ['block', 'transaction', 'sort_key', 'time', 'address', 'currency', 'sign', 'effect', 'valid', 'extra']; - - $tsv = ''; - - foreach ($events as $event) - { - $this_tsv = []; - - if ($event['address'] === '0x00') - $event['address'] = 'the-void'; - - if ($module->currency_format === CurrencyFormat::Static) - $event['currency'] = $module->currency; - else - $event['currency'] = ($module->complements ?? $module->module) . '/' . $event['currency']; - - $event['sign'] = (str_contains($event['effect'], '-')) ? '-1' : '1'; - - if ($module->privacy_model === PrivacyModel::Transparent) - { - $event['effect'] = str_replace('-', '', $event['effect']); - } - elseif ($module->privacy_model === PrivacyModel::Mixed) - { - if (in_array($event['effect'], ['-?', '+?'])) - $event['effect'] = null; - else - $event['effect'] = str_replace('-', '', $event['effect']); - } - else // Shielded - { - $event['effect'] = null; - } - - if (isset($event['failed'])) - $event['valid'] = ($event['failed'] === true || $event['failed'] === 't') ? '-1' : '1'; - else - $event['valid'] = '1'; - - if (isset($event['extra'])) - $event['extra'] = '\\\\x' . bin2hex($event['extra']); - - $this_tsv[] = $module->blockchain; - $this_tsv[] = $module->module; - - foreach ($tsv_fields as $f) - $this_tsv[] = (isset($event[$f])) ? $event[$f] : '\N'; - - if (in_array('extra_indexed', $module->events_table_fields)) - $this_tsv[] = (!is_null($event['extra_indexed'])) ? '\\\\x' . bin2hex($event['extra_indexed']) : '\N'; - - $tsv .= join(T, $this_tsv) . N; - } - - $fname = "Dumps/3xplor3r_{$module->blockchain}_{$module->module}_events_{$chosen_block_id}.tsv"; - - if (!file_exists('Dumps')) - mkdir('Dumps', 0777); - - $f = fopen($fname, 'w'); - fwrite($f, $tsv); - fclose($f); - + $fname = dump_tsv($module, $chosen_block_id); ddd("Dumped to {$fname}"); } elseif ($filter === '10') @@ -340,9 +276,8 @@ for ($i = $start_block_id; $i != 0; $i--) { echo "\nProcessing block #{$i} "; - + PB: $t0 = microtime(true); - try { $module->process_block($i); @@ -351,6 +286,7 @@ { echo cli_format_error('Requested exception'); usleep(250000); + goto PB; } $event_count = count($module->get_return_events() ?? []); @@ -359,6 +295,8 @@ $time = number_format(microtime(true) - $t0, 4); echo "with {$event_count} events and {$currency_count} currencies in {$time} seconds"; + if ($event_count > 0) + dump_tsv($module,$i); } } elseif ($chosen_option === 'PR') @@ -399,9 +337,8 @@ for ($i = $start_block_id; $i != $end_block_id; $i = $i + $increment) { echo "\nProcessing block #{$i} "; - + PR: $t0 = microtime(true); - try { $module->process_block($i); @@ -410,6 +347,7 @@ { echo cli_format_error('Requested exception'); usleep(250000); + goto PR; } $event_count = count($module->get_return_events() ?? []); @@ -417,6 +355,9 @@ $time = number_format(microtime(true) - $t0, 4); echo "with {$event_count} events and {$currency_count} currencies in {$time} seconds"; + + if ($event_count > 0) + dump_tsv($module,$i); } } elseif ($chosen_option === 'M') @@ -563,3 +504,151 @@ ddd($module->api_broadcast_transaction($data)); } +elseif ($chosen_option === 'AG') +{ + + $block_start = 3; + $chosen_module = $input_argv[0]; + $module_name = ''; + $tests_by_blocks = []; + $tests_by_blocks_processed = []; + if (is_numeric($chosen_module)) // Allow both selecting by number or by full module name + { + if (!isset($i_to_module[$chosen_module])) + die(cli_format_error('Wrong choice for the first param') . N); + $module_name = module_name_to_class($i_to_module[$chosen_module]); + } + else + { + if (!in_array($chosen_module, $available_modules)) + die(cli_format_error('Wrong choice for the 1st param') . N); + $module_name = module_name_to_class($chosen_module); + } + + $tests_class_name = $module_name . "Test"; + if (file_exists(__DIR__ . "/Modules/Tests/{$tests_class_name}.php")) + { + require_once __DIR__ . "/Modules/Tests/{$tests_class_name}.php"; + $tests_module = new ($tests_class_name)(); + $tests_by_blocks = $tests_module::$tests; + } + if (count($tests_by_blocks) > 0) + { + echo cli_format_bold('There are some tests. If you choose the same block or transaction it will be rewritten!!!') . N; + foreach ($tests_by_blocks as $b => $tests) + { + $block_processed = (string)$tests['block'] . (isset($tests['transaction']) ? $tests['transaction'] : ''); + $tests_by_blocks_processed[$block_processed] = $b; + echo cli_format_bold($tests['block'] . ((isset($tests['transaction']) ? ' transaction: ' . $tests['transaction'] : '')) . ' is tested') . N; + } + } + + do + { + echo cli_format_bold('Block number please...') . N; + + if (isset($argv[$block_start])) + { + $chosen_block_id = (int)$argv[$block_start]; + echo ":> {$chosen_block_id}\n"; + } else + { + $chosen_block_id = (int)readline(':> '); + } + $block_start++; + $input_argv[] = $chosen_block_id; + + if ($chosen_block_id !== MEMPOOL) + $module->process_block($chosen_block_id); + else + return; + + echo N; + + $filter = 'T'; + if ($filter === 'T') + { + echo cli_format_bold( + cli_format_reverse('') . ' for all events and currencies, ' . + cli_format_reverse('<{:transaction}>') . ' for a single transaction\'s events') . N; + + if (isset($argv[$block_start])) + { + $transaction = $argv[$block_start]; + echo ":> {$transaction}\n"; + } else { + $transaction = readline(':> '); + } + $block_start++; + $input_argv[] = $transaction; + + if ($transaction === 'A') + { + if (isset($tests_by_blocks_processed[$chosen_block_id])) + { + $tests_by_blocks[$tests_by_blocks_processed[$chosen_block_id]] = [ + 'block' => $chosen_block_id, + 'result' => serialize(['events' => $module->get_return_events(), 'currencies' => $module->get_return_currencies()]), + ]; + } else { + $tests_by_blocks[] = [ + 'block' => $chosen_block_id, + 'result' => serialize(['events' => $module->get_return_events(), 'currencies' => $module->get_return_currencies()]), + ]; + } + } else { + $filtered_events = []; + $events = $module->get_return_events(); + foreach ($events as $event) + { + if (!is_null($event['transaction']) && str_contains($event['transaction'], $transaction)) + $filtered_events[] = $event; + } + + $block_transaction_merged = $chosen_block_id . $transaction; + if (isset($tests_by_blocks_processed[$block_transaction_merged])) + { + $tests_by_blocks[$tests_by_blocks_processed[$block_transaction_merged]] = [ + 'block' => $chosen_block_id, + 'transaction' => $transaction, + 'events' => serialize(['events' => $filtered_events]), + ]; + } else { + $tests_by_blocks[] = [ + 'block' => $chosen_block_id, + 'transaction' => $transaction, + 'events' => serialize(['events' => $filtered_events]), + ]; + } + } + + } + + echo cli_format_bold( + cli_format_reverse('') . ' for break and generate tests file, ' . + cli_format_reverse('') . ' for continue' + ) . N; + + if (isset($argv[$block_start])) + { + $chosen_block_id = $argv[$block_start]; + echo ":> {$chosen_block_id}\n"; + } else + { + $chosen_block_id = readline(':> '); + } + $block_start++; + $input_argv[] = $chosen_block_id; + + if ($chosen_block_id === 'S') + { + autogen_test($tests_by_blocks, $module_name); + ddd(); + } + if ($chosen_block_id === 'C') + { + continue; + } + + }while(true); +} diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index f041e1f1..a9d83cad 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -5,6 +5,7 @@ - Core, UTXO modules, EVM modules * [Yulian Volianskyi](https://github.com/jzethar) - Beacon Chain modules + - AutoGenTest * [alexqrid](https://github.com/alexqrid) - TVM modules - BRC-20 module diff --git a/Engine/AutoGenTest.php b/Engine/AutoGenTest.php new file mode 100644 index 00000000..b54e8a83 --- /dev/null +++ b/Engine/AutoGenTest.php @@ -0,0 +1,37 @@ + %s, 'result' => '%s'],"; + $test_block_transaction_format = "['block' => %s, 'transaction' => '%s', 'result' => '%s'],"; + foreach ($tests_for_blocks as $i => $tests) + { + if(isset($tests['transaction'])) + $block_test .= sprintf($test_block_transaction_format, $tests['block'], $tests['transaction'], $tests['events']); + else + $block_test .= sprintf($test_block_format, $tests['block'], $tests['result']); + } + $tests = "\$tests = [" . $block_test . "];"; + print_in_file($tests, $module_name); +} + +function print_in_file(string $array2print, string $module_name) +{ + if (!file_exists(__DIR__ . "/../Modules/Tests/")) + mkdir(__DIR__ . "/../Modules/Tests/", 0777); + $initiator = " module block transaction sort_key time + // address currency sign effect valid extra ?extra_indexed + + $tsv_fields = ['block', 'transaction', 'sort_key', 'time', 'address', 'currency', 'sign', 'effect', 'valid', 'extra']; + + $tsv = ''; + $events = $module->get_return_events(); + + foreach ($events as $event) + { + $this_tsv = []; + + if ($event['address'] === '0x00') + $event['address'] = 'the-void'; + + if ($module->currency_format === CurrencyFormat::Static) + $event['currency'] = $module->currency; + else + $event['currency'] = ($module->complements ?? $module->module) . '/' . $event['currency']; + + $event['sign'] = (str_contains($event['effect'], '-')) ? '-1' : '1'; + + if ($module->privacy_model === PrivacyModel::Transparent) + { + $event['effect'] = str_replace('-', '', $event['effect']); + } + elseif ($module->privacy_model === PrivacyModel::Mixed) + { + if (in_array($event['effect'], ['-?', '+?'])) + $event['effect'] = null; + else + $event['effect'] = str_replace('-', '', $event['effect']); + } + else // Shielded + { + $event['effect'] = null; + } + + if (isset($event['failed'])) + $event['valid'] = ($event['failed'] === true || $event['failed'] === 't') ? '-1' : '1'; + else + $event['valid'] = '1'; + + if (isset($event['extra'])) + $event['extra'] = '\\\\x' . bin2hex($event['extra']); + + $this_tsv[] = $module->blockchain; + $this_tsv[] = $module->module; + + foreach ($tsv_fields as $f) + $this_tsv[] = (isset($event[$f])) ? $event[$f] : '\N'; + + if (in_array('extra_indexed', $module->events_table_fields)) + $this_tsv[] = (!is_null($event['extra_indexed'])) ? '\\\\x' . bin2hex($event['extra_indexed']) : '\N'; + + $tsv .= join(T, $this_tsv) . N; + } + + $fname = "Dumps/3xplor3r_{$module->blockchain}_{$module->module}_events_{$block_id}.tsv"; + + if (!file_exists('Dumps')) + mkdir('Dumps', 0777); + + $f = fopen($fname, 'w'); + fwrite($f, $tsv); + fclose($f); + return $fname; +} + /* The 3-Clause BSD License (BSD-3-Clause) * Copyright (c) 2016 ghostff * diff --git a/Init.php b/Init.php index 60c80a9b..b4cecdab 100644 --- a/Init.php +++ b/Init.php @@ -13,6 +13,7 @@ require_once __DIR__ . '/Engine/Requester.php'; require_once __DIR__ . '/Engine/Database.php'; require_once __DIR__ . '/Engine/ModuleInterface.php'; +require_once __DIR__ . '/Engine/AutoGenTest.php'; spl_autoload_register(function($class) { diff --git a/Modules/Tests/zkSyncEraMainModuleTest.php b/Modules/Tests/zkSyncEraMainModuleTest.php new file mode 100644 index 00000000..81316674 --- /dev/null +++ b/Modules/Tests/zkSyncEraMainModuleTest.php @@ -0,0 +1,12 @@ + 40521139, 'result' => 'a:2:{s:6:"events";a:10:{i:0;a:8:{s:11:"transaction";s:66:"0xa26adf0676a6753a61bd564210e2e7bc24c879f50b9bf29749a5c5db53dda53b";s:7:"address";s:42:"0xe5601264e9e00b7509fdf565102e042bedff254c";s:6:"effect";s:15:"-19859727250000";s:6:"failed";s:1:"f";s:5:"extra";s:1:"b";s:5:"block";i:40521139;s:4:"time";s:19:"2024-07-31 18:55:44";s:8:"sort_key";i:0;}i:1;a:8:{s:11:"transaction";s:66:"0xa26adf0676a6753a61bd564210e2e7bc24c879f50b9bf29749a5c5db53dda53b";s:7:"address";s:4:"0x00";s:6:"effect";s:14:"19859727250000";s:6:"failed";s:1:"f";s:5:"extra";s:1:"b";s:5:"block";i:40521139;s:4:"time";s:19:"2024-07-31 18:55:44";s:8:"sort_key";i:1;}i:2;a:8:{s:11:"transaction";s:66:"0xa26adf0676a6753a61bd564210e2e7bc24c879f50b9bf29749a5c5db53dda53b";s:7:"address";s:42:"0xe5601264e9e00b7509fdf565102e042bedff254c";s:6:"effect";s:2:"-0";s:6:"failed";s:1:"f";s:5:"extra";N;s:5:"block";i:40521139;s:4:"time";s:19:"2024-07-31 18:55:44";s:8:"sort_key";i:2;}i:3;a:8:{s:11:"transaction";s:66:"0xa26adf0676a6753a61bd564210e2e7bc24c879f50b9bf29749a5c5db53dda53b";s:7:"address";s:42:"0xca5824d2b23abb066d1e23e421ae631ac8823255";s:6:"effect";s:1:"0";s:6:"failed";s:1:"f";s:5:"extra";N;s:5:"block";i:40521139;s:4:"time";s:19:"2024-07-31 18:55:44";s:8:"sort_key";i:3;}i:4;a:8:{s:11:"transaction";s:66:"0x2e87630e0ecf700627d3da4376a19c1f70962017785778692a997d04795fede7";s:7:"address";s:42:"0x2ccb701acb575f4f734338bd6ac84401ff964a22";s:6:"effect";s:14:"-6429663000000";s:6:"failed";s:1:"f";s:5:"extra";s:1:"b";s:5:"block";i:40521139;s:4:"time";s:19:"2024-07-31 18:55:44";s:8:"sort_key";i:4;}i:5;a:8:{s:11:"transaction";s:66:"0x2e87630e0ecf700627d3da4376a19c1f70962017785778692a997d04795fede7";s:7:"address";s:4:"0x00";s:6:"effect";s:13:"6429663000000";s:6:"failed";s:1:"f";s:5:"extra";s:1:"b";s:5:"block";i:40521139;s:4:"time";s:19:"2024-07-31 18:55:44";s:8:"sort_key";i:5;}i:6;a:8:{s:11:"transaction";s:66:"0x2e87630e0ecf700627d3da4376a19c1f70962017785778692a997d04795fede7";s:7:"address";s:42:"0x2ccb701acb575f4f734338bd6ac84401ff964a22";s:6:"effect";s:2:"-0";s:6:"failed";s:1:"f";s:5:"extra";N;s:5:"block";i:40521139;s:4:"time";s:19:"2024-07-31 18:55:44";s:8:"sort_key";i:6;}i:7;a:8:{s:11:"transaction";s:66:"0x2e87630e0ecf700627d3da4376a19c1f70962017785778692a997d04795fede7";s:7:"address";s:42:"0x5155704bb41fde152ad3e1ae402e8e8b9ba335d3";s:6:"effect";s:1:"0";s:6:"failed";s:1:"f";s:5:"extra";N;s:5:"block";i:40521139;s:4:"time";s:19:"2024-07-31 18:55:44";s:8:"sort_key";i:7;}i:8;a:8:{s:11:"transaction";N;s:7:"address";s:4:"0x00";s:6:"effect";s:2:"-0";s:6:"failed";s:1:"f";s:5:"extra";s:1:"r";s:5:"block";i:40521139;s:4:"time";s:19:"2024-07-31 18:55:44";s:8:"sort_key";i:8;}i:9;a:8:{s:11:"transaction";N;s:7:"address";s:42:"0x0000000000000000000000000000000000000000";s:6:"effect";s:1:"0";s:6:"failed";s:1:"f";s:5:"extra";s:1:"r";s:5:"block";i:40521139;s:4:"time";s:19:"2024-07-31 18:55:44";s:8:"sort_key";i:9;}}s:10:"currencies";N;}'],['block' => 40521136, 'transaction' => '0x8544cc5773f307fe5319c2bbe1735771387d1287ed11b392d39187747b3ad569', 'result' => 'a:1:{s:6:"events";a:4:{i:0;a:8:{s:11:"transaction";s:66:"0x8544cc5773f307fe5319c2bbe1735771387d1287ed11b392d39187747b3ad569";s:7:"address";s:42:"0x768e3b10ebbfa2d72f055b3c982e0ca1a7069363";s:6:"effect";s:14:"-9627661500000";s:6:"failed";s:1:"f";s:5:"extra";s:1:"b";s:5:"block";i:40521136;s:4:"time";s:19:"2024-07-31 18:55:41";s:8:"sort_key";i:4;}i:1;a:8:{s:11:"transaction";s:66:"0x8544cc5773f307fe5319c2bbe1735771387d1287ed11b392d39187747b3ad569";s:7:"address";s:4:"0x00";s:6:"effect";s:13:"9627661500000";s:6:"failed";s:1:"f";s:5:"extra";s:1:"b";s:5:"block";i:40521136;s:4:"time";s:19:"2024-07-31 18:55:41";s:8:"sort_key";i:5;}i:2;a:8:{s:11:"transaction";s:66:"0x8544cc5773f307fe5319c2bbe1735771387d1287ed11b392d39187747b3ad569";s:7:"address";s:42:"0x768e3b10ebbfa2d72f055b3c982e0ca1a7069363";s:6:"effect";s:2:"-0";s:6:"failed";s:1:"f";s:5:"extra";N;s:5:"block";i:40521136;s:4:"time";s:19:"2024-07-31 18:55:41";s:8:"sort_key";i:6;}i:3;a:8:{s:11:"transaction";s:66:"0x8544cc5773f307fe5319c2bbe1735771387d1287ed11b392d39187747b3ad569";s:7:"address";s:42:"0xb774c13ba5a665713037c42a12f0ed9de70585cb";s:6:"effect";s:1:"0";s:6:"failed";s:1:"f";s:5:"extra";N;s:5:"block";i:40521136;s:4:"time";s:19:"2024-07-31 18:55:41";s:8:"sort_key";i:7;}}}'],]; +} diff --git a/Modules/zkSyncEraMainModule.php b/Modules/zkSyncEraMainModule.php index 2f3a90b0..78250603 100644 --- a/Modules/zkSyncEraMainModule.php +++ b/Modules/zkSyncEraMainModule.php @@ -27,5 +27,11 @@ function initialize() { return '0'; }; + + if (file_exists(__DIR__ . '/Tests/zkSyncEraMainModuleTest.php')) + { + require_once __DIR__ . '/Tests/zkSyncEraMainModuleTest.php'; + $this->tests = zkSyncEraMainModuleTest::$tests; + } } } From c84256756430ee0249933ec4c98618901eac5047 Mon Sep 17 00:00:00 2001 From: jzethar Date: Mon, 5 Aug 2024 22:19:56 +0500 Subject: [PATCH 2/3] Refactor tests including in CoreModule --- Modules/Common/CoreModule.php | 13 ++++++++++++- Modules/zkSyncEraMainModule.php | 6 ------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Modules/Common/CoreModule.php b/Modules/Common/CoreModule.php index bb83090f..9ab513b6 100644 --- a/Modules/Common/CoreModule.php +++ b/Modules/Common/CoreModule.php @@ -681,7 +681,18 @@ final public function post_process_block() final public function test() { if (!isset($this->tests)) - throw new DeveloperError('No tests defined for this module'); + { + $class_name = envm($this->module, 'CLASS', new DeveloperError("Nodes are not set in the config for module {$this->module}")) . 'Test'; + if (file_exists(__DIR__ . "/../Tests/{$class_name}.php")) + { + + require_once __DIR__ . "/../Tests/{$class_name}.php"; + $test_module = new $class_name(); + $this->tests = $test_module::$tests; + } else { + throw new DeveloperError('No tests defined for this module'); + } + } $errors = []; diff --git a/Modules/zkSyncEraMainModule.php b/Modules/zkSyncEraMainModule.php index 78250603..2f3a90b0 100644 --- a/Modules/zkSyncEraMainModule.php +++ b/Modules/zkSyncEraMainModule.php @@ -27,11 +27,5 @@ function initialize() { return '0'; }; - - if (file_exists(__DIR__ . '/Tests/zkSyncEraMainModuleTest.php')) - { - require_once __DIR__ . '/Tests/zkSyncEraMainModuleTest.php'; - $this->tests = zkSyncEraMainModuleTest::$tests; - } } } From 90fa02bbda16b0fb403d2da6ee5a9fab88b75343 Mon Sep 17 00:00:00 2001 From: jzethar Date: Mon, 5 Aug 2024 23:25:14 +0500 Subject: [PATCH 3/3] small fixes --- Modules/Common/CoreModule.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/Common/CoreModule.php b/Modules/Common/CoreModule.php index 9ab513b6..54e38dca 100644 --- a/Modules/Common/CoreModule.php +++ b/Modules/Common/CoreModule.php @@ -682,7 +682,7 @@ final public function test() { if (!isset($this->tests)) { - $class_name = envm($this->module, 'CLASS', new DeveloperError("Nodes are not set in the config for module {$this->module}")) . 'Test'; + $class_name = envm($this->module, 'CLASS') . 'Test'; if (file_exists(__DIR__ . "/../Tests/{$class_name}.php")) {