From b57310ffac2565a12594e3aa45d77bca7f6d3b35 Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Mon, 26 Aug 2024 19:59:46 -0600 Subject: [PATCH] EOF testing error codes for layout (#7522) Update the eof layout error codes to match codes in reference tests. This includes support for multiple possible errors for a specific test. Signed-off-by: Danno Ferrin --- .../evmtool/CodeValidationSubCommandTest.java | 12 +- .../evmtool/pretty-print/dangling-data.json | 2 +- .../state-test/create-invalid-eof.json | 2 +- .../ethereum/eof/EOFReferenceTestTools.java | 92 ++++++---- .../hyperledger/besu/evm/code/EOFLayout.java | 75 ++++---- .../hyperledger/besu/evm/code/CodeV1Test.java | 8 +- .../besu/evm/code/EOFLayoutTest.java | 173 +++++++++++------- 7 files changed, 225 insertions(+), 139 deletions(-) diff --git a/ethereum/evmtool/src/test/java/org/hyperledger/besu/evmtool/CodeValidationSubCommandTest.java b/ethereum/evmtool/src/test/java/org/hyperledger/besu/evmtool/CodeValidationSubCommandTest.java index d6b7359413c..9fe34b4836c 100644 --- a/ethereum/evmtool/src/test/java/org/hyperledger/besu/evmtool/CodeValidationSubCommandTest.java +++ b/ethereum/evmtool/src/test/java/org/hyperledger/besu/evmtool/CodeValidationSubCommandTest.java @@ -57,7 +57,8 @@ void testSingleInvalidViaInput() { EvmToolCommand parentCommand = new EvmToolCommand(bais, new PrintWriter(baos, true, UTF_8)); final CodeValidateSubCommand codeValidateSubCommand = new CodeValidateSubCommand(parentCommand); codeValidateSubCommand.run(); - assertThat(baos.toString(UTF_8)).contains("err: layout - EOF header byte 1 incorrect\n"); + assertThat(baos.toString(UTF_8)) + .contains("err: layout - invalid_magic EOF header byte 1 incorrect\n"); } @Test @@ -71,7 +72,7 @@ void testMultipleViaInput() { .contains( """ OK 1/0/0 - err: layout - EOF header byte 1 incorrect + err: layout - invalid_magic EOF header byte 1 incorrect OK 1/0/0 """); } @@ -97,7 +98,8 @@ void testSingleInvalidViaCli() { final CommandLine cmd = new CommandLine(codeValidateSubCommand); cmd.parseArgs(CODE_BAD_MAGIC); codeValidateSubCommand.run(); - assertThat(baos.toString(UTF_8)).contains("err: layout - EOF header byte 1 incorrect\n"); + assertThat(baos.toString(UTF_8)) + .contains("err: layout - invalid_magic EOF header byte 1 incorrect\n"); } @Test @@ -113,7 +115,7 @@ void testMultipleViaCli() { .contains( """ OK 1/0/0 - err: layout - EOF header byte 1 incorrect + err: layout - invalid_magic EOF header byte 1 incorrect OK 1/0/0 """); } @@ -154,7 +156,7 @@ void testBlankLinesAndCommentsSkipped() { .isEqualTo( """ OK 1/0/0 - err: layout - EOF header byte 1 incorrect + err: layout - invalid_magic EOF header byte 1 incorrect OK 1/0/0 """); } diff --git a/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/pretty-print/dangling-data.json b/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/pretty-print/dangling-data.json index 27833a1bb93..bdab829bbcd 100644 --- a/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/pretty-print/dangling-data.json +++ b/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/pretty-print/dangling-data.json @@ -4,5 +4,5 @@ "ef00010100040200010001040000000080000000ff" ], "stdin": "", - "stdout": "EOF layout is invalid - Dangling data after end of all sections\n" + "stdout": "EOF layout is invalid - invalid_section_bodies_size data after end of all sections\n" } \ No newline at end of file diff --git a/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/state-test/create-invalid-eof.json b/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/state-test/create-invalid-eof.json index dc786d61362..e2eb67602e9 100644 --- a/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/state-test/create-invalid-eof.json +++ b/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/state-test/create-invalid-eof.json @@ -71,7 +71,7 @@ } }, "stdout": [ - {"output":"","gasUsed":"0xd198","test":"create-eof","fork":"Prague","d":0,"g":0,"v":0,"postHash":"0x2a9c58298ba5d4ec86ca682b9fcc9ff67c3fc44dbd39f85a2f9b74bfe4e5178e","postLogsHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","pass":false,"error":"Invalid EOF Layout: Expected kind 1 but read kind 17"}, + {"output":"","gasUsed":"0xd198","test":"create-eof","fork":"Prague","d":0,"g":0,"v":0,"postHash":"0x2a9c58298ba5d4ec86ca682b9fcc9ff67c3fc44dbd39f85a2f9b74bfe4e5178e","postLogsHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","pass":false,"error":"Invalid EOF Layout: unexpected_header_kind expected 1 actual 17"}, {"pc":0,"op":239,"gas":"0x794068","gasCost":"0x0","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"INVALID","error":"Bad instruction"}, {"output":"","gasUsed":"0x7a1200","test":"create-eof","fork":"Cancun","d":0,"g":0,"v":0,"postHash":"0xaa80d89bc89f58da8de41d3894bd1a241896ff91f7a5964edaefb39e8e3a4a98","postLogsHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","pass":true,"error":"INVALID_OPERATION"} ] diff --git a/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/eof/EOFReferenceTestTools.java b/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/eof/EOFReferenceTestTools.java index 8621b5d08af..3c0c2dbbb2f 100644 --- a/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/eof/EOFReferenceTestTools.java +++ b/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/eof/EOFReferenceTestTools.java @@ -20,9 +20,11 @@ import java.util.Arrays; import java.util.Collection; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Map.Entry; +import com.google.common.base.Splitter; import org.apache.tuweni.bytes.Bytes; import org.hyperledger.besu.ethereum.referencetests.EOFTestCaseSpec; @@ -31,9 +33,7 @@ import org.hyperledger.besu.evm.Code; import org.hyperledger.besu.evm.EVM; import org.hyperledger.besu.evm.code.CodeInvalid; -import org.hyperledger.besu.evm.code.CodeV1; import org.hyperledger.besu.evm.code.EOFLayout; -import org.hyperledger.besu.evm.code.EOFLayout.EOFContainerMode; import org.hyperledger.besu.testutil.JsonTestParameters; public class EOFReferenceTestTools { @@ -124,6 +124,25 @@ public static void executeTest( // hardwire in the magic byte transaction checks if (evm.getMaxEOFVersion() < 1) { assertThat(expected.exception()).isEqualTo("EOF_InvalidCode"); + } else if (code.size() > evm.getEvmVersion().getMaxInitcodeSize()) { + // this check is in EOFCREATE and Transaction validator, but unit tests sniff it out. + assertThat(false) + .withFailMessage( + () -> + "No Expected exception, actual exception - container_size_above_limit " + + code.size()) + .isEqualTo(expected.result()); + if (name.contains("eip7692")) { + // if the test is from EEST, validate the exception name. + assertThat("container_size_above_limit") + .withFailMessage( + () -> + "Expected exception: %s actual exception: %s %d" + .formatted( + expected.exception(), "container_size_above_limit ", code.size())) + .containsIgnoringCase(expected.exception().replace("EOFException.", "")); + } + } else { EOFLayout layout = EOFLayout.parseEOF(code); @@ -134,39 +153,27 @@ public static void executeTest( } else { parsedCode = evm.getCodeUncached(code); } - if ("EOF_IncompatibleContainerKind".equals(expected.exception()) && parsedCode.isValid()) { - EOFContainerMode expectedMode = - EOFContainerMode.valueOf(containerKind == null ? "RUNTIME" : containerKind); - EOFContainerMode containerMode = - ((CodeV1) parsedCode).getEofLayout().containerMode().get(); - EOFContainerMode actualMode = - containerMode == null ? EOFContainerMode.RUNTIME : containerMode; - assertThat(actualMode) - .withFailMessage("Code did not parse to valid containerKind of " + expectedMode) - .isNotEqualTo(expectedMode); - } else { - if (expected.result()) { + if (expected.result()) { assertThat(parsedCode.isValid()) .withFailMessage( - () -> "Valid code failed with " + ((CodeInvalid) parsedCode).getInvalidReason()) - .isTrue(); - } else { - assertThat(parsedCode.isValid()) - .withFailMessage("Invalid code expected " + expected.exception() + " but was valid") - .isFalse(); - if (name.contains("eip7692")) { - // if the test is from EEST, validate the exception name. - assertThat(((CodeInvalid) parsedCode).getInvalidReason()) - .withFailMessage( - () -> - "Expected exception :%s actual exception: %s" - .formatted( - expected.exception(), - (parsedCode.isValid() - ? null - : ((CodeInvalid) parsedCode).getInvalidReason()))) - .containsIgnoringCase(expected.exception().replace("EOFException.", "")); - } + () -> "Valid code failed with " + ((CodeInvalid) parsedCode).getInvalidReason()) + .isTrue(); + } else { + assertThat(parsedCode.isValid()) + .withFailMessage("Invalid code expected " + expected.exception() + " but was valid") + .isFalse(); + if (name.contains("eip7692")) { + // if the test is from EEST, validate the exception name. + assertThat(((CodeInvalid) parsedCode).getInvalidReason()) + .withFailMessage( + () -> + "Expected exception :%s actual exception: %s" + .formatted( + expected.exception(), + (parsedCode.isValid() + ? null + : ((CodeInvalid) parsedCode).getInvalidReason()))) + .containsIgnoringCase(expected.exception().replace("EOFException.", "")); } } } else { @@ -178,6 +185,25 @@ public static void executeTest( + " actual exception - " + (layout.isValid() ? null : layout.invalidReason())) .isEqualTo(expected.result()); + if (name.contains("eip7692")) { + // if the test is from EEST, validate the exception name. + boolean exceptionMatched = false; + for (String e : Splitter.on('|').split(expected.exception())) { + if (layout + .invalidReason() + .toLowerCase(Locale.ROOT) + .contains(e.replace("EOFException.", "").toLowerCase(Locale.ROOT))) { + exceptionMatched = true; + break; + } + } + assertThat(exceptionMatched) + .withFailMessage( + () -> + "Expected exception :%s actual exception: %s" + .formatted(expected.exception(), layout.invalidReason())) + .isTrue(); + } } } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/code/EOFLayout.java b/evm/src/main/java/org/hyperledger/besu/evm/code/EOFLayout.java index d5abb05f868..7883b70d80f 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/code/EOFLayout.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/code/EOFLayout.java @@ -131,10 +131,10 @@ private static EOFLayout invalidLayout( private static String readKind(final ByteArrayInputStream inputStream, final int expectedKind) { int kind = inputStream.read(); if (kind == -1) { - return "Improper section headers"; + return "missing_headers_terminator Improper section headers"; } if (kind != expectedKind) { - return "Expected kind " + expectedKind + " but read kind " + kind; + return "unexpected_header_kind expected " + expectedKind + " actual " + kind; } return null; } @@ -217,7 +217,10 @@ public static EOFLayout parseEOF(final Bytes container, final boolean strictSize // This ReferenceEquality check is correct if ((strictSize || result != parsedContainer) && step.container.size() != parsedContainer.container.size()) { - return invalidLayout(container, parsedContainer.version, "subcontainer size mismatch"); + return invalidLayout( + container, + parsedContainer.version, + "invalid_section_bodies_size subcontainer size mismatch"); } if (step.index >= 0) { step.parentSubcontainers[step.index] = parsedContainer; @@ -233,18 +236,18 @@ private static EOFLayout parseEOF(final EOFParseStep step, final Queue MAX_SUPPORTED_VERSION || version < 1) { - return invalidLayout(step.container, version, "Unsupported EOF Version " + version); + return invalidLayout(step.container, version, "invalid_version " + version); } String error = readKind(inputStream, SECTION_TYPES); @@ -252,8 +255,11 @@ private static EOFLayout parseEOF(final EOFParseStep step, final Queue 1024) { return invalidLayout( step.container, version, - "Type section length incompatible with code section count - 0x" - + Integer.toHexString(codeSectionCount) - + " * 4 != 0x" - + Integer.toHexString(typesLength)); + "too_many_code_sections - 0x" + Integer.toHexString(codeSectionCount)); } - if (codeSectionCount > 1024) { + if (codeSectionCount * 4 != typesLength) { return invalidLayout( step.container, version, - "Too many code sections - 0x" + Integer.toHexString(codeSectionCount)); + "invalid_section_bodies_size Type section - 0x" + + Integer.toHexString(codeSectionCount) + + " * 4 != 0x" + + Integer.toHexString(typesLength)); } int[] codeSectionSizes = new int[codeSectionCount]; for (int i = 0; i < codeSectionCount; i++) { int size = readUnsignedShort(inputStream); if (size <= 0) { - return invalidLayout(step.container, version, "Invalid Code section size for section " + i); + return invalidLayout(step.container, version, "zero_section_size code " + i); } codeSectionSizes[i] = size; } @@ -303,7 +310,7 @@ private static EOFLayout parseEOF(final EOFParseStep step, final Queue 0x7f) { return invalidLayout( step.container, version, - "Type data input stack too large - 0x" + Integer.toHexString(typeData[i][0])); + "inputs_outputs_num_above_limit Type data input stack too large - 0x" + + Integer.toHexString(typeData[i][0])); } if (typeData[i][1] > 0x80) { return invalidLayout( step.container, version, - "Type data output stack too large - 0x" + Integer.toHexString(typeData[i][1])); + "inputs_outputs_num_above_limit - 0x" + Integer.toHexString(typeData[i][1])); } if (typeData[i][2] > 0x3ff) { return invalidLayout( step.container, version, - "Type data max stack too large - 0x" + Integer.toHexString(typeData[i][2])); + "max_stack_height_above_limit Type data max stack too large - 0x" + + Integer.toHexString(typeData[i][2])); } codeSections[i] = new CodeSection(codeSectionSize, typeData[i][0], typeData[i][1], typeData[i][2], pos); @@ -390,8 +401,7 @@ private static EOFLayout parseEOF(final EOFParseStep step, final Queue stackRetF() { return Stream.of( Arguments.of( "0 outputs at section 0", - "EOF Layout invalid - Code section at zero expected non-returning flag, but had return stack of 0", + "EOF Layout invalid - invalid_first_section_type want 0x80 (non-returning flag) has 0", 0, List.of(List.of("e4", 0, 0, 0), List.of("e4", 0, 0, 0))), Arguments.of( @@ -766,12 +766,12 @@ static Stream stackRetF() { List.of(List.of("00", 0, 0x80, 0), List.of("e4", 1, 1, 1), List.of("e4", 0, 0, 0))), Arguments.of( "more than 0 outputs section 0", - "EOF Layout invalid - Code section at zero expected non-returning flag, but had return stack of 0", + "EOF Layout invalid - invalid_first_section_type want 0x80 (non-returning flag) has 0", 0, List.of(List.of("44 50 e4", 0, 0, 1), List.of("4400", 0, 1, 1))), Arguments.of( "more than 0 outputs section 0", - "EOF Layout invalid - Code section at zero expected non-returning flag, but had return stack of 0", + "EOF Layout invalid - invalid_first_section_type want 0x80 (non-returning flag) has 0", 1, List.of(List.of("00", 0, 0, 0), List.of("44 e4", 0, 1, 1))), Arguments.of( diff --git a/evm/src/test/java/org/hyperledger/besu/evm/code/EOFLayoutTest.java b/evm/src/test/java/org/hyperledger/besu/evm/code/EOFLayoutTest.java index 006fe1632b9..2cce45830de 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/code/EOFLayoutTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/code/EOFLayoutTest.java @@ -29,162 +29,187 @@ public class EOFLayoutTest { public static Collection containersWithFormatErrors() { return Arrays.asList( new Object[][] { - {"EF", "No magic", "EOF Container too small", -1}, - {"FFFFFF", "Wrong magic", "EOF header byte 0 incorrect", -1}, - {"EFFF01010002020004006000AABBCCDD", "Invalid magic", "EOF header byte 1 incorrect", -1}, - {"EF00", "No version", "EOF Container too small", -1}, - {"EF0000010002020004006000AABBCCDD", "Invalid version", "Unsupported EOF Version 0", 0}, - {"EF0002010002020004006000AABBCCDD", "Invalid version", "Unsupported EOF Version 2", 2}, - { - "EF00FF010002020004006000AABBCCDD", - "Invalid version", - "Unsupported EOF Version 255", - 255 - }, - {"EF0001", "No header", "Improper section headers", 1}, - {"EF0001 00", "No code section", "Expected kind 1 but read kind 0", 1}, - {"EF0001 01", "No code section size", "Invalid Types section size", 1}, - {"EF0001 0100", "Code section size incomplete", "Invalid Types section size", 1}, - {"EF0001 010004", "No section terminator", "Improper section headers", 1}, - {"EF0001 010004 00", "No code section contents", "Expected kind 2 but read kind 0", 1}, - {"EF0001 010004 02", "No code section count", "Invalid Code section count", 1}, - {"EF0001 010004 0200", "Short code section count", "Invalid Code section count", 1}, - { - "EF0001 010004 020001", + {"EF", "No magic", "invalid_magic EOF Container too small", -1}, + {"FFFFFF", "Wrong magic", "invalid_magic EOF header byte 0 incorrect", -1}, + { + "EFFF01010002020004006000AABBCCDD", + "Invalid magic", + "invalid_magic EOF header byte 1 incorrect", + -1 + }, + {"EF00", "No version", "invalid_magic EOF Container too small", -1}, + {"EF0000010002020004006000AABBCCDD", "Invalid version", "invalid_version 0", 0}, + {"EF0002010002020004006000AABBCCDD", "Invalid version", "invalid_version 2", 2}, + {"EF00FF010002020004006000AABBCCDD", "Invalid version", "invalid_version 255", 255}, + {"EF0001", "No header", "missing_headers_terminator Improper section headers", 1}, + {"EF0001 00", "No code section", "unexpected_header_kind expected 1 actual 0", 1}, + { + "EF0001 01", "No code section size", - "Invalid Code section size for section 0", + "invalid_type_section_size Invalid Types section size (mod 4 != 0)", 1 }, { - "EF0001 010004 02000100", - "Short code section size", - "Invalid Code section size for section 0", + "EF0001 0100", + "Code section size incomplete", + "invalid_type_section_size Invalid Types section size (mod 4 != 0)", 1 }, + { + "EF0001 010004", + "No section terminator", + "missing_headers_terminator Improper section headers", + 1 + }, + { + "EF0001 010004 00", + "No code section contents", + "unexpected_header_kind expected 2 actual 0", + 1 + }, + { + "EF0001 010004 02", + "No code section count", + "incomplete_section_number Too few code sections", + 1 + }, + { + "EF0001 010004 0200", + "Short code section count", + "incomplete_section_number Too few code sections", + 1 + }, + {"EF0001 010004 020001", "No code section size", "zero_section_size code 0", 1}, + {"EF0001 010004 02000100", "Short code section size", "zero_section_size code 0", 1}, { "EF0001 010008 0200020001", "No code section size multiple codes", - "Invalid Code section size for section 1", + "zero_section_size code 1", 1 }, { "EF0001 010008 020002000100", "No code section size multiple codes", - "Invalid Code section size for section 1", + "zero_section_size code 1", 1 }, - {"EF0001 010004 0200010001 04", "No data section size", "Invalid Data section size", 1}, + {"EF0001 010004 0200010001 04", "No data section size", "incomplete_data_header", 1}, + {"EF0001 010004 0200010001 0400", "Short data section size", "incomplete_data_header", 1}, { - "EF0001 010004 0200010001 0400", - "Short data section size", - "Invalid Data section size", + "EF0001 010004 0200010001 040000", + "No Terminator", + "missing_headers_terminator Improper section headers", + 1 + }, + { + "EF0001 010004 0200010002 040000 00", + "No type section", + "invalid_section_bodies_size Incomplete type section", 1 }, - {"EF0001 010004 0200010001 040000", "No Terminator", "Improper section headers", 1}, - {"EF0001 010004 0200010002 040000 00", "No type section", "Incomplete type section", 1}, { "EF0001 010004 0200010002 040001 040001 00 DA DA", "Duplicate data sections", - "Expected kind 0 but read kind 4", + "unexpected_header_kind expected 0 actual 4", 1 }, { "EF0001 010004 0200010002 040000 00 00", "Incomplete type section", - "Incomplete type section", + "invalid_section_bodies_size Incomplete type section", 1 }, { "EF0001 010008 02000200020002 040000 00 00000000FE", "Incomplete type section", - "Incomplete type section", + "invalid_section_bodies_size Incomplete type section", 1 }, { "EF0001 010008 0200010001 040000 00 00000000 FE ", "Incorrect type section size", - "Type section length incompatible with code section count - 0x1 * 4 != 0x8", + "invalid_section_bodies_size Type section - 0x1 * 4 != 0x8", 1 }, { "EF0001 010008 02000200010001 040000 00 0100000000000000 FE FE", "Incorrect section zero type input", - "Code section does not have zero inputs and outputs", + "invalid_first_section_type must be zero input non-returning", 1 }, { "EF0001 010008 02000200010001 040000 00 0001000000000000 FE FE", "Incorrect section zero type output", - "Code section does not have zero inputs and outputs", + "invalid_first_section_type must be zero input non-returning", 1 }, { "EF0001 010004 0200010002 040000 00 00000000 ", "Incomplete code section", - "Incomplete code section 0", + "invalid_section_bodies_size code section 0", 1 }, { "EF0001 010004 0200010002 040000 00 00000000 FE", "Incomplete code section", - "Incomplete code section 0", + "invalid_section_bodies_size code section 0", 1 }, { "EF0001 010008 02000200020002 040000 00 00800000 00000000 FEFE ", "No code section multiple", - "Incomplete code section 1", + "invalid_section_bodies_size code section 1", 1 }, { "EF0001 010008 02000200020002 040000 00 00800000 00000000 FEFE FE", "Incomplete code section multiple", - "Incomplete code section 1", + "invalid_section_bodies_size code section 1", 1 }, { "EF0001 010004 0200010001 040003 00 00800000 FE DEADBEEF", "Excess data section", - "Dangling data after end of all sections", + "invalid_section_bodies_size data after end of all sections", 1 }, { "EF0001 0200010001 040001 00 FE DA", "type section missing", - "Expected kind 1 but read kind 2", + "unexpected_header_kind expected 1 actual 2", 1 }, { "EF0001 010004 040001 00 00000000 DA", "code section missing", - "Expected kind 2 but read kind 4", + "unexpected_header_kind expected 2 actual 4", 1 }, { "EF0001 010004 0200010001 00 00000000 FE", "data section missing", - "Expected kind 4 but read kind 0", + "unexpected_header_kind expected 4 actual 0", 1 }, { "EF0001 040001 00 DA", "type and code section missing", - "Expected kind 1 but read kind 4", + "unexpected_header_kind expected 1 actual 4", 1 }, { "EF0001 0200010001 00 FE", "type and data section missing", - "Expected kind 1 but read kind 2", + "unexpected_header_kind expected 1 actual 2", 1 }, { "EF0001 010004 00 00000000", "code and data sections missing", - "Expected kind 2 but read kind 0", + "unexpected_header_kind expected 2 actual 0", 1 }, - {"EF0001 00", "all sections missing", "Expected kind 1 but read kind 0", 1}, + {"EF0001 00", "all sections missing", "unexpected_header_kind expected 1 actual 0", 1}, { "EF0001 011004 020401" + " 0001".repeat(1025) @@ -192,18 +217,33 @@ public static Collection containersWithFormatErrors() { + " 00000000".repeat(1025) + " FE".repeat(1025), "no data section, 1025 code sections", - "Too many code sections - 0x401", + "too_many_code_sections - 0x401", + 1 + }, + { + "ef000101000002000003000000", + "All kinds zero size", + "incomplete_section_number Too few code sections", + 1 + }, + { + "ef0001010000020001000103000000ef", + "Zero type size ", + "invalid_section_bodies_size Type section - 0x1 * 4 != 0x0", 1 }, - {"ef000101000002000003000000", "All kinds zero size", "Invalid Types section size", 1}, - {"ef0001010000020001000103000000ef", "Zero type size ", "Invalid Types section size", 1}, { "ef0001010004020001000003000000", "Zero code section length", - "Invalid Code section size for section 0", + "zero_section_size code 0", + 1 + }, + { + "ef000101000402000003000000", + "Zero code sections", + "incomplete_section_number Too few code sections", 1 }, - {"ef000101000402000003000000", "Zero code sections", "Invalid Code section count", 1}, }); } @@ -241,31 +281,31 @@ public static Collection typeSectionTests() { { "EF0001 010008 02000200020002 040000 00 0100000000000000", "Incorrect section zero type input", - "Code section does not have zero inputs and outputs", + "invalid_first_section_type must be zero input non-returning", 1 }, { "EF0001 010008 02000200020002 040000 00 0001000000000000", "Incorrect section zero type output", - "Code section does not have zero inputs and outputs", + "invalid_first_section_type must be zero input non-returning", 1 }, { "EF0001 010010 0200040001000200020002 040000 00 00800000 F0000000 00010000 02030000 FE 5000 3000 8000", "inputs too large", - "Type data input stack too large - 0xf0", + "inputs_outputs_num_above_limit Type data input stack too large - 0xf0", 1 }, { "EF0001 010010 0200040001000200020002 040000 00 00800000 01000000 00F00000 02030000 FE 5000 3000 8000", "outputs too large", - "Type data output stack too large - 0xf0", + "inputs_outputs_num_above_limit - 0xf0", 1 }, { "EF0001 010010 0200040001000200020002 040000 00 00000400 01000000 00010000 02030400 FE 5000 3000 8000", "stack too large", - "Type data max stack too large - 0x400", + "max_stack_height_above_limit Type data max stack too large - 0x400", 1 }, { @@ -336,13 +376,13 @@ public static Collection subContainers() { { "EF00 01 010004 0200010001 0300010015 040000 00 00800000 00 (EF0001 010004 0200010001 040000 00 00800000 00ff)", "dangling data in subcontainer", - "subcontainer size mismatch", + "invalid_section_bodies_size subcontainer size mismatch", 1 }, { "EF00 01 010004 0200010001 0300010014 040000 00 00800000 00 (EF0001 010004 0200010001 040000 00 00800000 00ff)", "dangling data in container", - "Dangling data after end of all sections", + "invalid_section_bodies_size data after end of all sections", 1 }, }); @@ -363,6 +403,11 @@ void test( final Bytes container = Bytes.fromHexString(containerString.replaceAll("[^a-fxA-F0-9]", "")); final EOFLayout layout = EOFLayout.parseEOF(container, true); + if (failureReason != null) { + assertThat(failureReason) + .withFailMessage("Error string should start with a reference test error code") + .matches("^[a-zA-Z]+_.*"); + } assertThat(layout.version()).isEqualTo(expectedVersion); assertThat(layout.invalidReason()).isEqualTo(failureReason); assertThat(layout.container()).isEqualTo(container);