package door import ( "flag" "fmt" "io/ioutil" "os" "runtime" "strings" "testing" "time" ) func TestMenuRender(t *testing.T) { bracket := ColorText("BLUE") option := ColorText("BRI GREEN") upper := ColorText("CYAN") lower := ColorText("MAGENTA") render := MakeMenuRender(bracket, option, upper, lower) // Fake menu line input := "[X] BUGZ test" got := render(input) expected := 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 Exeeding Width did not panic.") } }() m := 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) { tmpFile, err := ioutil.TempFile(os.TempDir(), "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 server, client := setupSockets() // We're not testing closed connections, so: defer server.Close() defer client.Close() // unicode 90x40 response buffer := []byte("\x1b[1;1R\x1b[2;3R\x1b[40;90R") server.Write(buffer) runtime.Gosched() // Access Fd (File descriptor) of client for dropfile var fd int = socket_to_fd(client) defer close_fd(fd) // Create door32.sys file dfc := DropfileConfig{2, fd, 1800, "Test BBSID", 1701, "Real Username", "Handle", 880, 28, 0, 12} 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)) tmpFile.Close() d := Door{} // 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("menu-test-12.log") // 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) } // These are the commands sent to detect ... throw this all away. buffer = make([]byte, 1024) server.SetReadDeadline(time.Now().Add(time.Millisecond * 20)) _, err = server.Read(buffer) if err != nil { t.Errorf("server.Read: %s", err) } // t.Errorf("Buffer : %#v\n", buffer[:r]) server.SetReadDeadline(time.Time{}) // Ready to test! m := 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 // BUG: I can't use \x1b[A because of the way extended codes work there. keys := "\x00\x50\x00\x50\r" // down, down, ENTER server.Write([]byte(keys)) time.Sleep(time.Millisecond) runtime.Gosched() if d.Disconnect() { t.Errorf("Disconnected") } choice = m.Choose(&d) if choice < 0 { t.Errorf("Error <0 from Choose: %d", choice) } option := 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 server.SetReadDeadline(time.Now().Add(time.Millisecond * 50)) r, err := server.Read(buffer) if err != nil { t.Errorf("server.Read: %s", err) } server.SetReadDeadline(time.Time{}) 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 = "\x00\x48\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 server.SetReadDeadline(time.Now().Add(time.Millisecond * 50)) r, err = server.Read(buffer) if err != nil { t.Errorf("server.Read: %s", err) } server.SetReadDeadline(time.Time{}) // 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 server.SetReadDeadline(time.Now().Add(time.Millisecond * 50)) r, err = server.Read(buffer) if err != nil { t.Errorf("server.Read: %s", err) } server.SetReadDeadline(time.Time{}) // 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 server.SetReadDeadline(time.Now().Add(time.Millisecond * 50)) r, err = server.Read(buffer) if err != nil { t.Errorf("server.Read: %s", err) } server.SetReadDeadline(time.Time{}) // 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 // i/o timeout server.SetReadDeadline(time.Now().Add(time.Millisecond * 100)) r, err = server.Read(buffer) if err != nil { t.Errorf("server.Read: %s", err) } server.SetReadDeadline(time.Time{}) // 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 server.SetReadDeadline(time.Now().Add(time.Millisecond * 50)) r, err = server.Read(buffer) if err != nil { t.Errorf("server.Read: %s", err) } server.SetReadDeadline(time.Time{}) // output = string(buffer[:r]) server.Close() client.Close() d.Write("\x00") time.Sleep(time.Millisecond) }