my ts rlp decoder seems to work
i feel like i would have more confidence in my code if i didn't test it
This commit is contained in:
@@ -20,6 +20,13 @@
|
||||
<h5>Failed case log:</h5>
|
||||
<pre id="b64-assershins"></pre>
|
||||
|
||||
<h1>RLP Encode/Decode Tests</h1>
|
||||
<p>Current case: <span id="rlp-current-case"></span></p>
|
||||
<p>Total cases: <span id="rlp-total-cases"></span></p>
|
||||
<button id="rlp-go">Go!</button>
|
||||
<h5>Failed case log:</h5>
|
||||
<pre id="rlp-assershins"></pre>
|
||||
|
||||
<script type="module" src="dist/test.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
import * as rlpcases from './rlpcases.js';
|
||||
|
||||
export const rlp = rlpcases.cases;
|
||||
|
||||
export const base58 = [
|
||||
{encoded: "1",
|
||||
decoded: new Uint8Array([0])},
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,8 +2,52 @@ import * as cases from './cases.js';
|
||||
|
||||
import * as b64 from './jex_include/local-vanillae-0.1.0/dist/base64.js';
|
||||
import * as b58 from './jex_include/local-vanillae-0.1.0/dist/base58.js';
|
||||
import * as rlp from './jex_include/local-vanillae-0.1.0/dist/rlp.js';
|
||||
|
||||
function uint8arr_eq(a: Uint8Array, b: Uint8Array) {
|
||||
|
||||
function deepeq(dd1: rlp.decoded_data, dd2: rlp.decoded_data): boolean {
|
||||
// if both are Uint8Arrays
|
||||
if ((dd1 instanceof Uint8Array) && (dd2 instanceof Uint8Array)) {
|
||||
return uint8arr_eq(dd1, dd2);
|
||||
}
|
||||
// if both are Arrays
|
||||
else if ((dd1 instanceof Array) && (dd2 instanceof Array)) {
|
||||
return arr_eq(dd1, dd2);
|
||||
}
|
||||
// otherwise
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function arr_eq(a: Array<rlp.decoded_data>, b: Array<rlp.decoded_data>): boolean {
|
||||
// make sure they have the same length
|
||||
if (a.length !== b.length) {
|
||||
return false;
|
||||
}
|
||||
// they have the same length now
|
||||
else {
|
||||
let len : number = a.length;
|
||||
// loop over the items
|
||||
for (let i = 0;
|
||||
i < len;
|
||||
i++)
|
||||
{
|
||||
let a_elt : rlp.decoded_data = a[i];
|
||||
let b_elt : rlp.decoded_data = b[i];
|
||||
let eq : boolean = deepeq(a_elt, b_elt);
|
||||
// if they are not equal, break and return false
|
||||
if (!eq) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// at the end, if we havent' proven ourselves wrong yet,
|
||||
// the arrays are equal
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function uint8arr_eq(a: Uint8Array, b: Uint8Array): boolean {
|
||||
// first test if the length
|
||||
if (a.length !== b.length) {
|
||||
return false;
|
||||
@@ -108,15 +152,58 @@ function b58_tests(): void {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function rlp_tests(): void {
|
||||
// @ts-ignore ts can't prove to itself that the element exists
|
||||
let rlp_pre : HTMLElement = document.getElementById('rlp-assershins');
|
||||
// @ts-ignore ts can't prove to itself that the element exists
|
||||
let rlp_casen : HTMLElement = document.getElementById('rlp-current-case');
|
||||
let case_n : number = 1;
|
||||
|
||||
for(let this_case of cases.rlp) {
|
||||
// i love this type error
|
||||
// can't set the inner html to a number
|
||||
// but a string plus a number is totally cool
|
||||
rlp_casen.innerHTML = '' + case_n;
|
||||
case_n++;
|
||||
|
||||
let {encoded, decoded} = this_case;
|
||||
//let my_encoded = rlp.encode(decoded);
|
||||
let my_decoded = rlp.decode(encoded).decoded_data;
|
||||
|
||||
//let encodes_correctly = (encoded === my_encoded);
|
||||
let decodes_correctly = deepeq(decoded, my_decoded);
|
||||
|
||||
//if (!encodes_correctly) {
|
||||
// rlp_pre.innerHTML +=
|
||||
// '===================================\n' +
|
||||
// 'FAILED CASE: encode\n' +
|
||||
// '===================================\n' +
|
||||
// 'decoded : ' + decoded + '\n' +
|
||||
// 'expected: ' + encoded + '\n' +
|
||||
// 'actual : ' + my_encoded + '\n\n' ;
|
||||
//}
|
||||
|
||||
if (!decodes_correctly) {
|
||||
rlp_pre.innerHTML +=
|
||||
'===================================\n' +
|
||||
'FAILED CASE: decode\n' +
|
||||
'===================================\n' +
|
||||
'encoded : ' + encoded + '\n' +
|
||||
'expected: ' + decoded + '\n' +
|
||||
'actual : ' + my_decoded + '\n\n' ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function main(): void {
|
||||
// @ts-ignore ts can't prove to itself that the element exists
|
||||
document.getElementById('b64-total-cases')!.innerHTML = cases.base64.length;
|
||||
// @ts-ignore ts can't prove to itself that the element exists
|
||||
document.getElementById('b64-total-cases')!.innerHTML = '' + cases.base64.length;
|
||||
document.getElementById('b64-go')!.onclick = b64_tests;
|
||||
|
||||
// @ts-ignore ts can't prove to itself that the element exists
|
||||
document.getElementById('b58-total-cases')!.innerHTML = cases.base58.length;
|
||||
// @ts-ignore ts can't prove to itself that the element exists
|
||||
document.getElementById('b58-total-cases')!.innerHTML = '' + cases.base58.length;
|
||||
document.getElementById('b58-go')!.onclick = b58_tests;
|
||||
|
||||
document.getElementById('rlp-total-cases')!.innerHTML = '' + cases.rlp.length;
|
||||
document.getElementById('rlp-go')!.onclick = rlp_tests;
|
||||
}
|
||||
main();
|
||||
|
||||
@@ -2,15 +2,83 @@
|
||||
%-compile(export_all).
|
||||
|
||||
-mode(compile).
|
||||
%-compile(nowarn_unused).
|
||||
-compile([nowarn_unused_function]).
|
||||
|
||||
main([]) ->
|
||||
% Decoded cases
|
||||
DecodedCases = rand_decode_datas(100_000),
|
||||
DecodedCases = rand_decode_datas(10_000),
|
||||
%io:format("~p~n", [DecodedCases]),
|
||||
io:format("~s~n", [format_cases_py(DecodedCases)]),
|
||||
io:format("~s~n", [format_cases_js(DecodedCases)]),
|
||||
ok.
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%
|
||||
%%% JS FORMATTING %%%
|
||||
%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
format_cases_js(Cases) ->
|
||||
format_stringlist_js(lists:map(fun format_case_js/1, Cases)).
|
||||
|
||||
% format a list of strings into a python list
|
||||
format_stringlist_js(List) ->
|
||||
% stringlist commas are the same in python/js, so reusing python
|
||||
["import * as rlp from './jex_include/local-vanillae-0.1.0/dist/rlp.js';\n"
|
||||
"\n"
|
||||
"type rlpcases = {decoded: rlp.decoded_data, encoded: Uint8Array};\n"
|
||||
"\n"
|
||||
"// @ts-ignore never mind; jesus christ\n"
|
||||
"export const cases : Array<rlpcases> = [\n", slcommas(List, []), "];"].
|
||||
|
||||
% input: decoded_data
|
||||
% format a case as
|
||||
% {'decoded_data': <js term for rlist>,
|
||||
% 'encoded_bytes': new Uint8Array([B1, B2, B3, ...])}
|
||||
format_case_js(DecodedData_rlist) ->
|
||||
% EncodedData_bytes = rlp:encode(
|
||||
% DD_js = format_data_js(DecodedData_rlist),
|
||||
EncodedData_bytes = rlp:encode(DecodedData_rlist),
|
||||
EncodedBytes_py = format_bytes_js(EncodedData_bytes),
|
||||
DecodedData_py = format_data_js(DecodedData_rlist),
|
||||
[" {'decoded': ", DecodedData_py, ",\n",
|
||||
" 'encoded': ", EncodedBytes_py, "}"].
|
||||
|
||||
|
||||
format_data_js(List) when is_list(List) ->
|
||||
format_list_js(List);
|
||||
format_data_js(Bytes) when is_binary(Bytes) ->
|
||||
format_bytes_js(Bytes).
|
||||
|
||||
|
||||
format_list_js(List) ->
|
||||
[$[, js_lcommas(List, []), $]].
|
||||
|
||||
|
||||
% similar to commas/2 below but for a list
|
||||
% cases
|
||||
% - list is empty -> special case
|
||||
% - exactly one element -> special case
|
||||
% - two or more elements -> peel off one at a time until terminal case of exactly one
|
||||
% initial input empty, so return empty
|
||||
js_lcommas([], []) ->
|
||||
[];
|
||||
% one item left, do not add comma
|
||||
js_lcommas([Item], Acc) ->
|
||||
[Acc, format_data_js(Item)];
|
||||
% two or more items left, add comma
|
||||
js_lcommas([Item | Rest], Acc) ->
|
||||
js_lcommas(Rest, [Acc, format_data_js(Item), ", "]).
|
||||
|
||||
% format a bytestring as "bytes([Byte1, Byte2, ...])"
|
||||
format_bytes_js(Bytes) ->
|
||||
% commas are the same as in python so reusing that
|
||||
Commas = commas(Bytes, []),
|
||||
["new Uint8Array([", Commas, "])"].
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%% PYTHON FORMATTING %%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
format_cases_py(Cases) ->
|
||||
format_stringlist_py(lists:map(fun format_case_py/1, Cases)).
|
||||
|
||||
@@ -99,6 +167,11 @@ commas(<<B, Rest/binary>>, Acc) ->
|
||||
commas(Rest, [Acc, integer_to_list(B), ", "]).
|
||||
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%% INVERSE PROPERTY TEST %%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
% test that the inverse property is correct
|
||||
|
||||
test_inverse() ->
|
||||
@@ -121,6 +194,12 @@ check_inverse(DecodedData) ->
|
||||
{DeEncodedData, <<>>} = rlp:decode(rlp:encode(DecodedData)),
|
||||
DeEncodedData =:= DecodedData.
|
||||
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%% RANDOM CASE GENERATION %%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
%mkcase(DecodedData) ->
|
||||
% Encoded = rlp:encode(DecodedData),
|
||||
% {Deencoded, <<>>} = rlp:decode(
|
||||
|
||||
Reference in New Issue
Block a user