package packer import ( "math/rand" "net" "testing" "time" ) var src = Addr{ family: "IPv4", addr: "192.168.1.101", port: 6743, } var dst = Addr{ family: "IPv4", port: 80, scheme: "http", } var domain = "ex1.telebit.io" var payload = []byte("Hello, World!") type testHandler struct { conns map[string]*Conn chunksParsed int bytesRead int } func (th *testHandler) WriteMessage(a Addr, b []byte) { th.chunksParsed++ addr := &a _, ok := th.conns[addr.Network()] if !ok { rconn, wconn := net.Pipe() conn := &Conn{ updated: time.Now(), relayRemoteAddr: *addr, relay: rconn, local: wconn, } th.conns[addr.Network()] = conn } th.bytesRead += len(b) } func TestParse1WholeBlock(t *testing.T) { testParseNBlocks(t, 1) } func TestParse2WholeBlocks(t *testing.T) { testParseNBlocks(t, 2) } func TestParse3WholeBlocks(t *testing.T) { testParseNBlocks(t, 3) } func TestParse2Addrs(t *testing.T) { testParseNBlocks(t, 4) } func TestParse3Addrs(t *testing.T) { testParseNBlocks(t, 5) } func TestParseBy1(t *testing.T) { testParseByN(t, 1) } func TestParseByPrimes(t *testing.T) { testParseByN(t, 2) testParseByN(t, 3) testParseByN(t, 5) testParseByN(t, 7) testParseByN(t, 11) testParseByN(t, 13) testParseByN(t, 17) testParseByN(t, 19) testParseByN(t, 23) testParseByN(t, 29) testParseByN(t, 31) testParseByN(t, 37) testParseByN(t, 41) testParseByN(t, 43) testParseByN(t, 47) } func TestParseByRand(t *testing.T) { testParseByN(t, 0) } func TestParse1AndRest(t *testing.T) { th := &testHandler{ conns: map[string]*Conn{}, } p := NewParser(th) h, b, err := Encode(src, dst, domain, payload) if nil != err { t.Fatal(err) } raw := append(h, b...) n, err := p.Write(raw[:1]) if nil != err { t.Fatal(err) } m, err := p.Write(raw[1:]) if nil != err { t.Fatal(err) } if 1 != len(th.conns) { t.Fatal("should have parsed one connection") } if 1 != th.chunksParsed { t.Fatal("should have parsed 1 chunck(s)") } if len(payload) != th.bytesRead { t.Fatalf("should have parsed a payload of %d bytes, but saw %d\n", len(payload), th.bytesRead) } if n+m != len(raw) { t.Fatalf("should have parsed all %d bytes, not just %d\n", n, len(raw)) } } func TestParseRestAnd1(t *testing.T) { th := &testHandler{ conns: map[string]*Conn{}, } p := NewParser(th) h, b, err := Encode(src, dst, domain, payload) if nil != err { t.Fatal(err) } raw := append(h, b...) i := len(raw) n, err := p.Write(raw[:i-1]) if nil != err { t.Fatal(err) } m, err := p.Write(raw[i-1:]) if nil != err { t.Fatal(err) } if 1 != len(th.conns) { t.Fatal("should have parsed one connection") } if 2 != th.chunksParsed { t.Fatal("should have parsed 2 chunck(s)") } if len(payload) != th.bytesRead { t.Fatalf("should have parsed a payload of %d bytes, but saw %d\n", len(payload), th.bytesRead) } if n+m != len(raw) { t.Fatalf("should have parsed all %d bytes, not just %d\n", n, len(raw)) } } func testParseByN(t *testing.T, n int) { //fmt.Printf("[debug] parse by %d\n", n) th := &testHandler{ conns: map[string]*Conn{}, } p := NewParser(th) h, b, err := Encode(src, dst, domain, payload) if nil != err { t.Fatal(err) } raw := append(h, b...) count := 0 nChunk := 0 b = raw for { r := 24 c := len(b) if 0 == c { break } i := n if 0 == n { if c < r { r = c } i = 1 + rand.Intn(r+1) } if c < i { i = c } // TODO shouldn't this cause an error? //a := b[:i][0] a := b[:i] b = b[i:] nw, err := p.Write(a) if nil != err { t.Fatal(err) } count += nw if count > len(h) { nChunk++ } } if 1 != len(th.conns) { t.Fatalf("should have parsed one connection, not %d", len(th.conns)) } if nChunk != th.chunksParsed { t.Fatalf("should have parsed %d chunk(s), not %d", nChunk, th.chunksParsed) } if len(payload) != th.bytesRead { t.Fatalf("should have parsed a payload of %d bytes, but saw %d\n", len(payload), th.bytesRead) } if count != len(raw) { t.Fatalf("should have parsed all %d bytes, not just %d\n", len(raw), count) } } func testParseNBlocks(t *testing.T, count int) { th := &testHandler{ conns: map[string]*Conn{}, } nAddr := 1 if count > 2 { nAddr = count - 2 } p := NewParser(th) raw := []byte{} for i := 0; i < count; i++ { if i > 2 { copied := src src = copied src.port += i } h, b, err := Encode(src, dst, domain, payload) if nil != err { t.Fatal(err) } raw = append(raw, h...) raw = append(raw, b...) } n, err := p.Write(raw) if nil != err { t.Fatal(err) } if nAddr != len(th.conns) { t.Fatalf("should have parsed %d connection(s)", nAddr) } if count != th.chunksParsed { t.Fatalf("should have parsed %d chunk(s)", count) } if count*len(payload) != th.bytesRead { t.Fatalf("should have parsed a payload of %d bytes, but saw %d\n", count*len(payload), th.bytesRead) } if n != len(raw) { t.Fatalf("should have parsed all %d bytes, not just %d\n", len(raw), n) } }