package hopp import "io" import "net" import "bytes" import "errors" import "slices" import "testing" // some of these tests spawn goroutines that can signal a failure. // abide by the documentation for testing.T (https://pkg.go.dev/testing#T): // // A test ends when its Test function returns or calls any of the methods // FailNow, Fatal, Fatalf, SkipNow, Skip, or Skipf. Those methods, as well as // the Parallel method, must be called only from the goroutine running the // Test function. // // The other reporting methods, such as the variations of Log and Error, may // be called simultaneously from multiple goroutines. func TestConnA(test *testing.T) { payloads := []string { "hello", "world", "When the impostor is sus!", } network := "tcp" addr := "localhost:7959" // server listener, err := net.Listen(network, addr) if err != nil { test.Fatal(err) } defer listener.Close() go func() { test.Log("SERVER listening") conn, err := listener.Accept() if err != nil { test.Error("SERVER", err); return } defer conn.Close() a := AdaptA(conn, ServerSide) trans, err := a.OpenTrans() if err != nil { test.Error("SERVER", err); return } defer trans.Close() for method, payload := range payloads { test.Log("SERVER", method, payload) err := trans.Send(uint16(method), []byte(payload)) if err != nil { test.Error("SERVER", err); return } } }() // client test.Log("CLIENT dialing") conn, err := net.Dial(network, addr) if err != nil { test.Fatal("CLIENT", err) } test.Log("CLIENT dialed") a := AdaptA(conn, ClientSide) defer a.Close() test.Log("CLIENT accepting transaction") trans, err := a.AcceptTrans() if err != nil { test.Fatal("CLIENT", err) } test.Log("CLIENT accepted transaction") defer trans.Close() for method, payload := range payloads { test.Log("CLIENT waiting...") gotMethod, gotPayloadBytes, err := trans.Receive() if err != nil { test.Fatal("CLIENT", err) } gotPayload := string(gotPayloadBytes) test.Log("CLIENT", gotMethod, gotPayload) if int(gotMethod) != method { test.Errorf("CLIENT method not equal") } if gotPayload != payload { test.Errorf("CLIENT payload not equal") } } _, _, err = trans.Receive() if !errors.Is(err, io.EOF) { test.Fatal("CLIENT wrong error:", err) } test.Log("CLIENT done") // TODO test error from trans/connection closed by other side } func TestEncodeMessageA(test *testing.T) { buffer := new(bytes.Buffer) payload := []byte { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 } err := encodeMessageA(buffer, 0x5800FEABC3104F04, 0x6B12, payload) correct := []byte { 0x58, 0x00, 0xFE, 0xAB, 0xC3, 0x10, 0x4F, 0x04, 0x6B, 0x12, 0x00, 0x06, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, } if err != nil { test.Fatal(err) } if got, correct := buffer.Bytes(), correct; !slices.Equal(got, correct) { test.Fatalf("not equal: %v %v", got, correct) } } func TestEncodeMessageAErr(test *testing.T) { buffer := new(bytes.Buffer) payload := make([]byte, 0x10000) err := encodeMessageA(buffer, 0x5800FEABC3104F04, 0x6B12, payload) if !errors.Is(err, ErrPayloadTooLarge) { test.Fatalf("wrong error: %v", err) } } func TestDecodeMessageA(test *testing.T) { transID, method, payload, err := decodeMessageA(bytes.NewReader([]byte { 0x58, 0x00, 0xFE, 0xAB, 0xC3, 0x10, 0x4F, 0x04, 0x6B, 0x12, 0x00, 0x06, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, })) if err != nil { test.Fatal(err) } if got, correct := transID, int64(0x5800FEABC3104F04); got != correct { test.Fatalf("not equal: %v %v", got, correct) } if got, correct := method, uint16(0x6B12); got != correct { test.Fatalf("not equal: %v %v", got, correct) } correctPayload := []byte { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 } if got, correct := payload, correctPayload; !slices.Equal(got, correct) { test.Fatalf("not equal: %v %v", got, correct) } } func TestDecodeMessageAErr(test *testing.T) { _, _, _, err := decodeMessageA(bytes.NewReader([]byte { 0x58, 0x00, 0xFE, 0xAB, 0xC3, 0x10, 0x4F, 0x04, 0x6B, 0x12, 0x01, 0x06, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, })) if !errors.Is(err, io.ErrUnexpectedEOF) { test.Fatalf("wrong error: %v", err) } }