package unit; import java.util.*; /** * Unit test for tokio-0001: CWE-407 in AnyDelimiterCodec. * * tokio-0001 (HIGH): * File: tokio-util/src/codec/any_delimiter_codec.rs:146 * Symbol: AnyDelimiterCodec::decode — Vec::contains() called per buffer byte * Defect: For each byte in the receive buffer (N bytes), the codec calls * seek_delimiters.contains(b) which is a linear scan over D delimiter * bytes: O(D) per byte, O(N×D) total per decode call. * Fix: At construction time, convert seek_delimiters into a [bool; 256] * lookup table. Each check becomes delimiter_table[b as usize]: O(1). * * Modeled here in Java: * Rust Vec::contains() ≡ boolean[] linear scan (defective) * Rust [bool; 256] indexing ≡ boolean[] direct index (fixed) * Comparison counts tracked at the membership-test site. * * Expected at N=4096 bytes, D=16 delimiters: * defective comparisons = N × D = 65,536 * fixed comparisons = N = 4,096 * ratio = 16× */ public class AnyDelimiterCodecTest { // ========================================================================= // tokio-0001 model: per-byte delimiter check, Vec linear scan vs lookup table // ========================================================================= /** * Defective decoder: for each byte in the buffer, scan the delimiter list * linearly (Vec::contains). * * Returns the index of the first delimiter byte found, or -1. * comparisons counts every element examined during scans. */ static class DefectiveDecoder { final byte[] delimiters; long comparisons = 0; DefectiveDecoder(byte[] delimiters) { this.delimiters = delimiters; } /** * Scan buf[0..len) for any delimiter byte. * For each byte b: linearly scan delimiters (O(D) per byte). */ int findFirstDelimiter(byte[] buf, int len) { for (int i = 0; i < len; i++) { byte b = buf[i]; // Vec::contains(b) — O(D) linear scan for (int d = 0; d < delimiters.length; d++) { comparisons++; if (delimiters[d] == b) { return i; } } } return -1; } } /** * Fixed decoder: pre-built boolean[256] lookup table at construction time. * For each byte b: delimiter_table[b & 0xFF] — O(1). * comparisons counts one operation per byte checked. */ static class FixedDecoder { final boolean[] delimiterTable = new boolean[256]; long comparisons = 0; FixedDecoder(byte[] delimiters) { for (byte d : delimiters) { delimiterTable[d & 0xFF] = true; } } /** * Scan buf[0..len) for any delimiter byte using the lookup table. */ int findFirstDelimiter(byte[] buf, int len) { for (int i = 0; i < len; i++) { comparisons++; // one array-index lookup per byte if (delimiterTable[buf[i] & 0xFF]) { return i; } } return -1; } } // ========================================================================= // Tests // ========================================================================= /** * Test 1 — Correctness: defective and fixed decoders agree on first delimiter position. * * Buffer: bytes 0..127 sequentially. Delimiters: {10, 44, 59} (\n , ;). * First delimiter in the buffer should be byte value 10 at position 10. */ static void testCorrectnessMatch() { byte[] delimiters = {10, 44, 59}; // \n , ; byte[] buf = new byte[128]; for (int i = 0; i < 128; i++) buf[i] = (byte) i; DefectiveDecoder def = new DefectiveDecoder(delimiters); FixedDecoder fix = new FixedDecoder(delimiters); int defPos = def.findFirstDelimiter(buf, buf.length); int fixPos = fix.findFirstDelimiter(buf, buf.length); assert defPos == fixPos : "position mismatch: defective=" + defPos + " fixed=" + fixPos; assert defPos == 10 : "expected delimiter at position 10 (\\n); got " + defPos; System.out.println("PASS testCorrectnessMatch"); } /** * Test 2 — No delimiter: both decoders return -1 when no delimiter present. * * Buffer filled with 0xFF (non-delimiter). Delimiters: {10, 44, 59}. */ static void testNoDelimiterFound() { byte[] delimiters = {10, 44, 59}; int N = 1024; byte[] buf = new byte[N]; Arrays.fill(buf, (byte) 0xFF); DefectiveDecoder def = new DefectiveDecoder(delimiters); FixedDecoder fix = new FixedDecoder(delimiters); int defPos = def.findFirstDelimiter(buf, N); int fixPos = fix.findFirstDelimiter(buf, N); assert defPos == -1 : "defective should return -1; got " + defPos; assert fixPos == -1 : "fixed should return -1; got " + fixPos; // Defective scanned all N×D pairs; fixed scanned N assert def.comparisons == (long) N * delimiters.length : "defective comparisons should be N*D=" + (long) N * delimiters.length + "; got " + def.comparisons; assert fix.comparisons == N : "fixed comparisons should be N=" + N + "; got " + fix.comparisons; System.out.println("PASS testNoDelimiterFound"); } /** * Test 3 — tokio-0001: O(N×D) vs O(N) ratio at N=4096, D=16. * * Worst-case: buffer contains no delimiter bytes (full scan). * Defective: 4096 × 16 = 65,536 comparisons. * Fixed: 4,096 comparisons. * Ratio: 16×. */ static void testRatioAtScale() { int N = 4096; int D = 16; byte[] delimiters = new byte[D]; // Use bytes 128..143 as delimiters — none appear in the buffer (filled with 0) for (int i = 0; i < D; i++) delimiters[i] = (byte) (128 + i); byte[] buf = new byte[N]; // all zeros — no delimiter matches DefectiveDecoder def = new DefectiveDecoder(delimiters); FixedDecoder fix = new FixedDecoder(delimiters); def.findFirstDelimiter(buf, N); fix.findFirstDelimiter(buf, N); long expectedDef = (long) N * D; long expectedFix = N; assert def.comparisons == expectedDef : "defective comparisons should be N*D=" + expectedDef + "; got " + def.comparisons; assert fix.comparisons == expectedFix : "fixed comparisons should be N=" + expectedFix + "; got " + fix.comparisons; double ratio = (double) def.comparisons / fix.comparisons; assert ratio >= D : "ratio should be >= D=" + D + "; got " + ratio; System.out.printf( "PASS testRatioAtScale (N=%d D=%d defective=%d fixed=%d ratio=%.1fx)%n", N, D, def.comparisons, fix.comparisons, ratio); } /** * Test 4 — Delimiter at start: both return position 0 immediately. * * Buffer starts with a delimiter byte. */ static void testDelimiterAtStart() { byte[] delimiters = {(byte) 0xAB}; byte[] buf = {(byte) 0xAB, 0, 1, 2, 3}; DefectiveDecoder def = new DefectiveDecoder(delimiters); FixedDecoder fix = new FixedDecoder(delimiters); assert def.findFirstDelimiter(buf, buf.length) == 0 : "defective should find delimiter at position 0"; assert fix.findFirstDelimiter(buf, buf.length) == 0 : "fixed should find delimiter at position 0"; // Defective: 1 comparison (found on first byte, first delimiter) assert def.comparisons == 1 : "defective should make 1 comparison; got " + def.comparisons; // Fixed: 1 lookup assert fix.comparisons == 1 : "fixed should make 1 comparison; got " + fix.comparisons; System.out.println("PASS testDelimiterAtStart"); } // ========================================================================= public static void main(String[] args) { testCorrectnessMatch(); testNoDelimiterFound(); testRatioAtScale(); testDelimiterAtStart(); System.out.println("4/4 PASS"); } }