package door import ( "flag" "fmt" "net" "os" "runtime" "strings" "testing" "time" ) func TestMenuRender(t *testing.T) { var bracket string = ColorText("BLUE") var option string = ColorText("BRI GREEN") var upper string = ColorText("CYAN") var lower string = ColorText("MAGENTA") var render ColorRender = MakeMenuRender(bracket, option, upper, lower) // Fake menu line var input string = "[X] BUGZ test" var got string = render(input) var expected string = bracket + "[" + option + "X" + bracket + "]" expected += lower + " " + upper + "BUGZ" + lower + " test" if got != expected { t.Errorf("MenuRender expected %#v, got %#v", expected, got) } } func TestMenuSize(t *testing.T) { defer func() { if r := recover(); r == nil { t.Error("Menu Exceeding Width did not panic.") } }() var m Menu = Menu{Panel: Panel{Width: 5, X: 1, Y: 1, Style: DOUBLE, }} // len("[A] ABC") = 7 (which is > 5) m.AddSelection("A", "ABC") } func TestMenuConnection(t *testing.T) { var tmpFile *os.File var err error tmpFile, err = os.CreateTemp("", "test-*") if err != nil { panic("Cannot create temporary file") } // Remember to clean up the file afterwards defer os.Remove(tmpFile.Name()) // establish network socket connection to set Comm_handle var server, client net.Conn server, client = setupSockets() // We're not testing closed connections, so: defer server.Close() defer client.Close() // pre-load unicode 90x40 response var buffer []byte = []byte(UnicodeWidthHeight(90, 40)) // "\x1b[1;1R\x1b[2;3R\x1b[40;90R") _, err = server.Write(buffer) if err != nil { t.Error("server.Write:", err) } // Access Fd (File descriptor) of client for dropfile var fd int = socket_to_fd(client) defer close_fd(fd) // Create door32.sys file var node int = 8 var dfc DropfileConfig = DropfileConfig{2, fd, 1800, "Test BBSID", 1701, "Real Username", "Handle", 880, 28, 0, node} _, err = tmpFile.WriteString(fmt.Sprintf("%d\n%d\n%d\n%s\n%d\n%s\n%s\n%d\n%d\n%d\n%d\n", dfc.Comm_type, dfc.Comm_handle, dfc.Baudrate, dfc.BBSID, dfc.User_number, dfc.Real_name, dfc.Handle, dfc.Security_level, dfc.Time_left, dfc.Emulation, dfc.Node)) if err != nil { t.Error("tmpFile.WriteString:", err) } err = tmpFile.Close() if err != nil { t.Error("tmpFile.Close:", err) } var d Door = Door{} // Reset global variables Unicode = false CP437 = false Full_CP437 = false Width = 0 Height = 0 // If I call d.Init() more then once flag complains about flag redefined. // Reset flags flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError) // preset commandline args so door can init os.Args = []string{"door", "-d", tmpFile.Name()} d.Init("menu-test") defer d.Close() // clean up log file - not needed in tests defer os.Remove(fmt.Sprintf("menu-test-%d.log", node)) // Ok! if !Unicode { t.Errorf("Unicode not true %t", Unicode) } if Width != 90 { t.Errorf("Width not 90: %d", Width) } if Height != 40 { t.Errorf("Height not 40: %d", Height) } clear_socket(server, t) /* // These are the commands sent to detect ... throw this all away. buffer = make([]byte, 1024) err = server.SetReadDeadline(time.Now().Add(time.Millisecond * 20)) if err != nil { t.Error("server.SetReadDeadLine:", err) } _, err = server.Read(buffer) if err != nil { t.Errorf("server.Read: %s", err) } // t.Errorf("Buffer : %#v\n", buffer[:r]) err = server.SetReadDeadline(time.Time{}) if err != nil { t.Error("server.SetReadDeadLine:", err) } */ // Ready to test! var m Menu = Menu{Panel: Panel{Width: 10, X: 2, Y: 2, Style: DOUBLE, }} // Use simple renders for testing m.SelectedR = func(text string) string { return ColorText("BLACK ON WHITE") + text } m.UnselectedR = func(text string) string { return ColorText("WHI ON BLA") + text } m.AddSelection("A", "ART") m.AddSelection("B", "BOO") m.AddSelection("C", "Cat") var choice int // preload the key buffer with commands var keys string = "\x00\x50\x1b[B\r" // down, down, ENTER _, err = server.Write([]byte(keys)) if err != nil { t.Error("server.Write:", err) } time.Sleep(time.Millisecond) if d.Disconnect() { t.Errorf("Disconnected") } choice = m.Choose(&d) if choice < 0 { t.Errorf("Error <0 from Choose: %d", choice) } var option rune = m.GetOption(choice) if choice != 3 { t.Errorf("Expected menu option 3, got %d / %c", choice, option) } if option != 'C' { t.Errorf("Expected menu option C, got %c / %d", option, choice) } // Read the display output output := clear_socket(server, t) /* err = server.SetReadDeadline(time.Now().Add(time.Millisecond * 50)) if err != nil { t.Error("server.SetReadDeadLine:", err) } var r int r, err = server.Read(buffer) if err != nil { t.Errorf("server.Read: %s", err) } err = server.SetReadDeadline(time.Time{}) if err != nil { t.Error("server.SetReadDeadLine:", err) } output := string(buffer[:r]) */ // t.Errorf("OUTPUT: (len %d) %#v", r, output) parts := strings.SplitAfter(output, "H") for _, part := range parts { t.Logf("Got: %#v", part) } keys = "\x1b[A\r" // up, ENTER _, err = server.Write([]byte(keys)) if err != nil { t.Errorf("server.Write: %#v", err) } time.Sleep(time.Millisecond) runtime.Gosched() if d.Disconnect() { t.Errorf("Disconnected") } m.Chosen = 1 choice = m.Choose(&d) if choice < 0 { t.Errorf("Error <0 from Choose: %d", choice) } option = m.GetOption(choice) if choice != 1 { t.Errorf("Expected menu option 1, got %d / %c", choice, option) } if option != 'A' { t.Errorf("Expected menu option A, got %c / %d", option, choice) } // Read the display output clear_socket(server, t) /* err = server.SetReadDeadline(time.Now().Add(time.Millisecond * 50)) if err != nil { t.Error("server.SetReadDeadLine:", err) } _, err = server.Read(buffer) if err != nil { t.Errorf("server.Read: %s", err) } err = server.SetReadDeadline(time.Time{}) if err != nil { t.Error("server.SetReadDeadLine:", err) } */ // TODO: Check Menu output and verify it is correct. // output = string(buffer[:r]) // Test HOME, END, selecting an option, 8 & 2. keys = "\x00\x4f\r" // END, ENTER _, err = server.Write([]byte(keys)) if err != nil { t.Errorf("server.Write: %#v", err) } time.Sleep(time.Millisecond) if d.Disconnect() { t.Errorf("Disconnected") } m.Chosen = 1 choice = m.Choose(&d) if choice < 0 { t.Errorf("Error <0 from Choose: %d", choice) } option = m.GetOption(choice) if choice != 3 || option != 'C' { t.Errorf("Expected 3/C, got %d/%c", choice, option) } // Read the display output output = clear_socket(server, t) /* err = server.SetReadDeadline(time.Now().Add(time.Millisecond * 50)) if err != nil { t.Error("server.SetReadDeadLine:", err) } _, err = server.Read(buffer) if err != nil { t.Errorf("server.Read: %s", err) } err = server.SetReadDeadline(time.Time{}) if err != nil { t.Error("server.SetReadDeadLine:", err) } */ // output = string(buffer[:r]) keys = "\x00\x47\r" // HOME, ENTER _, err = server.Write([]byte(keys)) if err != nil { t.Errorf("server.Write: %#v", err) } time.Sleep(time.Millisecond) m.Chosen = 2 choice = m.Choose(&d) if choice < 0 { t.Errorf("Error <0 from Choose: %d", choice) } option = m.GetOption(choice) if choice != 1 || option != 'A' { t.Errorf("Expected 1/A, got %d/%c", choice, option) } // Read the display output output = clear_socket(server, t) /* err = server.SetReadDeadline(time.Now().Add(time.Millisecond * 50)) if err != nil { t.Error("server.SetReadDeadLine:", err) } _, err = server.Read(buffer) if err != nil { t.Errorf("server.Read: %s", err) } err = server.SetReadDeadline(time.Time{}) if err != nil { t.Error("server.SetReadDeadLine:", err) } */ // output = string(buffer[:r]) _, err = server.Write([]byte("B")) if err != nil { t.Errorf("server.Write: %#v", err) } time.Sleep(time.Millisecond) m.Chosen = 0 choice = m.Choose(&d) if choice < 0 { t.Errorf("Error <0 from Choose: %d", choice) } option = m.GetOption(choice) if choice != 2 || option != 'B' { t.Errorf("Expected 2/B, got %d/%c", choice, option) } // Read the display output output = clear_socket(server, t) /* // i/o timeout err = server.SetReadDeadline(time.Now().Add(time.Millisecond * 100)) if err != nil { t.Error("server.SetReadDeadLine:", err) } _, err = server.Read(buffer) if err != nil { t.Errorf("server.Read: %s", err) } err = server.SetReadDeadline(time.Time{}) if err != nil { t.Error("server.SetReadDeadLine:", err) } */ // output = string(buffer[:r]) keys = "2\r" // "Down", ENTER _, err = server.Write([]byte(keys)) if err != nil { t.Errorf("server.Write: %#v", err) } time.Sleep(time.Millisecond) m.Chosen = 1 choice = m.Choose(&d) if choice < 0 { t.Errorf("Error <0 from Choose: %d", choice) } option = m.GetOption(choice) if choice != 3 || option != 'C' { t.Errorf("Expected 3/C, got %d/%c", choice, option) } // Read the display output output = clear_socket(server, t) /* err = server.SetReadDeadline(time.Now().Add(time.Millisecond * 50)) if err != nil { t.Error("server.SetReadDeadLine:", err) } _, err = server.Read(buffer) if err != nil { t.Errorf("server.Read: %s", err) } err = server.SetReadDeadline(time.Time{}) if err != nil { t.Error("server.SetReadDeadLine:", err) } */ // output = string(buffer[:r]) server.Close() client.Close() // d.Write("\x00") time.Sleep(time.Millisecond) }