Browse Source

Updated to LIFOBuffer, fixed input bug. Tests!

Steve Thielemann 3 years ago
parent
commit
53a6dc96b6
4 changed files with 208 additions and 21 deletions
  1. 29 3
      door/door.go
  2. 12 0
      door/door_test.go
  3. 9 18
      door/input.go
  4. 158 0
      door/input_test.go

+ 29 - 3
door/door.go

@@ -20,7 +20,6 @@ package door
 
 import (
 	"bufio"
-	"container/list"
 	"flag"
 	"fmt"
 	"os"
@@ -42,6 +41,34 @@ var Height int                        // Screen height detected
 var Width int                         // Screen width detected
 var Inactivity int64 = 120            // Inactivity timeout
 
+type LIFOBuffer struct {
+	data  []int
+	index int
+}
+
+func (b *LIFOBuffer) Empty() bool {
+	return b.index == 0
+}
+
+func (b *LIFOBuffer) Push(value int) {
+	if b.index+1 > len(b.data) {
+		b.data = append(b.data, value)
+		b.index++
+	} else {
+		b.data[b.index] = value
+		b.index++
+	}
+}
+
+func (b *LIFOBuffer) Pop() int {
+	if b.index == 0 {
+		panic("Attempting to Pop from empty LIFOBuffer.")
+	}
+
+	b.index--
+	return b.data[b.index]
+}
+
 /*
 door32.sys:
 
@@ -79,7 +106,7 @@ type Door struct {
 	Disconnected bool
 	TimeOut      time.Time // Fixed point in time, when time expires
 	StartTime    time.Time
-	Pushback     *list.List
+	Pushback     LIFOBuffer
 }
 
 // Return the amount of time left as time.Duration
@@ -206,7 +233,6 @@ func (d *Door) detect() {
 // detect terminal capabilities.
 func (d *Door) Init() {
 	var dropfile string
-	d.Pushback = list.New()
 
 	flag.StringVar(&dropfile, "d", "", "Path to dropfile")
 	flag.Parse()

+ 12 - 0
door/door_test.go

@@ -86,6 +86,18 @@ func TestReadDropFile(t *testing.T) {
 	startDelta := start.Sub(d.StartTime)
 	timeoutDelta := timeout.Sub(d.TimeOut)
 
+	left := d.TimeLeft()
+	used := d.TimeUsed()
+
+	if used.Seconds() > 1 {
+		t.Errorf("Time Used (from door) > 1 second: %#v", used)
+	}
+
+	time_left_seconds := dfc.Time_left * 60
+
+	if time_left_seconds-int(left.Seconds()) > 1 {
+		t.Errorf("Time Left differences > 1 second: test %#v door %#v", time_left_seconds, left)
+	}
 	if startDelta.Seconds() > 1 {
 		t.Errorf("Start Time differences: test %#v door %#v delta %#v", start, d.StartTime, startDelta)
 	}

+ 9 - 18
door/input.go

@@ -110,10 +110,8 @@ func (d *Door) getch() int {
 }
 
 func (d *Door) getkey_or_pushback() int {
-	if d.Pushback.Len() != 0 {
-		e := d.Pushback.Front()
-		d.Pushback.Remove(e)
-		return e.Value.(int)
+	if !d.Pushback.Empty() {
+		return d.Pushback.Pop()
 	}
 
 	if false {
@@ -152,7 +150,8 @@ func (d *Door) GetKey() int {
 			// wasn't an error
 			if c2 != 0x00 && c2 != 0x0a {
 				// wasn't 0x00 or 0x0a
-				d.Pushback.PushFront(c2)
+				d.Pushback.Push(c2)
+				// fmt.Printf("Push 0x0d trailer %d / %x\n", c2, c2)
 			}
 		}
 		return c
@@ -235,7 +234,7 @@ func (d *Door) GetKey() int {
 		c2 = d.getkey_or_pushback()
 		for c2 > 0 {
 			if c2 == 0x1b {
-				d.Pushback.PushBack(c2)
+				d.Pushback.Push(c2)
 				break
 			}
 			extended += string(byte(c2))
@@ -320,6 +319,10 @@ func (d *Door) WaitKey(secs int64, usecs int64) int {
 		return -2
 	}
 
+	if !d.Pushback.Empty() {
+		return d.GetKey()
+	}
+
 	var fdsetRead syscall.FdSet
 
 retry:
@@ -355,18 +358,6 @@ retry:
 	}
 
 	return d.GetKey()
-
-	// var buffer []byte   -- 0 byte buffer.  doh!
-	buffer := make([]byte, 1)
-	r, err := syscall.Read(d.READFD, buffer)
-	if r != 1 {
-		// I'm getting write error here... (when disconnected)
-		fmt.Printf("Read said ready, but didn't read a character %d %v.\n", r, err)
-		// hangup
-		d.Disconnected = true
-		return -2
-	}
-	return int(buffer[0])
 }
 
 // Outputs spaces and backspaces

+ 158 - 0
door/input_test.go

@@ -0,0 +1,158 @@
+package door
+
+import (
+	"fmt"
+	"io/ioutil"
+	"net"
+	"os"
+	"testing"
+)
+
+func TestDoorInputConnection(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
+	sock, err := net.Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		panic(err)
+	}
+
+	defer sock.Close()
+
+	// Get address of listening socket
+	address := sock.Addr().String()
+
+	client, err := net.Dial("tcp", address)
+
+	if err != nil {
+		panic(err)
+	}
+
+	defer client.Close()
+
+	server, err := sock.Accept()
+
+	if err != nil {
+		panic(err)
+	}
+
+	defer server.Close()
+
+	sock.Close()
+
+	// Ok, we have a server socket, and the client socket (that the door would talk to)
+	// t.Logf("Server: %#v\n", server)
+	// t.Logf("Client: %#v\n", client)
+
+	// unicode 190x43 response
+	buffer := []byte("\x1b[1;1R\x1b[2;3R\x1b[43;190R")
+	server.Write(buffer)
+
+	// Access Fd (File descriptor) of client for dropfile
+	client_conn := client.(*net.TCPConn)
+	client_file, err := client_conn.File()
+
+	var fd int = int(client_file.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{}
+	// preset commandline args so door can init
+	os.Args = []string{"door", "-d", tmpFile.Name()}
+	d.Init()
+
+	// Ok!
+	if !Unicode {
+		t.Errorf("Unicode not true %t", Unicode)
+	}
+
+	if Width != 190 {
+		t.Errorf("Width not 190: %d", Width)
+	}
+
+	if Height != 43 {
+		t.Errorf("Height not 43: %d", Height)
+	}
+
+	keytest := map[string][]int{
+		"\x1b":                             []int{0x1b},
+		"\x0d\x00":                         []int{0x0d},
+		"\x0d\x0a":                         []int{0x0d},
+		"\x0dCQ":                           []int{0x0d, 'C', 'Q'},
+		"\x0dA":                            []int{0x0d, 'A'},
+		"\x0dCAT":                          []int{0x0d, 'C', 'A', 'T'},
+		"\x00\x50\x00\x48\x00\x4b\x00\x4d": []int{XKEY_DOWN_ARROW, XKEY_UP_ARROW, XKEY_LEFT_ARROW, XKEY_RIGHT_ARROW},
+		"\x00\x47\x00\x4f\x00\x49\x00\x51": []int{XKEY_HOME, XKEY_END, XKEY_PGUP, XKEY_PGDN},
+		"\x00\x3b\x00\x3c\x00\x3d\x00\x3e": []int{XKEY_F1, XKEY_F2, XKEY_F3, XKEY_F4},
+		"\x00\x3f\x00\x40\x00\x41\x00\x42": []int{XKEY_F5, XKEY_F6, XKEY_F7, XKEY_F8},
+		"\x00\x43\x00\x44\x00\x52\x00\x53": []int{XKEY_F9, XKEY_F10, XKEY_INSERT, XKEY_DELETE},
+		"\x1b[A\x1b[B\x1b[C\x1b[D":         []int{XKEY_UP_ARROW, XKEY_DOWN_ARROW, XKEY_RIGHT_ARROW, XKEY_LEFT_ARROW},
+		"\x1b[H\x1b[F\x1b[K\x1b[V\x1b[U":   []int{XKEY_HOME, XKEY_END, XKEY_END, XKEY_PGUP, XKEY_PGDN},
+		"\x1b[5~\x1b[6~":                   []int{XKEY_PGUP, XKEY_PGDN},
+		"\x1bOP\x1bOQ\x1bOR\x1bOS":         []int{XKEY_F1, XKEY_F2, XKEY_F3, XKEY_F4},
+		"\x1b[15~\x1b[17~\x1b[18~\x1b[19~": []int{XKEY_F5, XKEY_F6, XKEY_F7, XKEY_F8},
+	}
+
+	for send, get := range keytest {
+		buffer := []byte(send)
+		server.Write(buffer)
+
+		recv := make([]int, 0)
+		for {
+			input := d.WaitKey(0, 50)
+			if input != -1 {
+				recv = append(recv, input)
+			} else {
+				break
+			}
+		}
+
+		if len(recv) != len(get) {
+			t.Errorf("Send %#v, LEN expected %#v, got %#v", send, get, recv)
+		} else {
+			matches := true
+			for idx, i := range get {
+				if recv[idx] != i {
+					matches = false
+					break
+				}
+			}
+			if !matches {
+				t.Errorf("Send %#v, MATCH expected %#v, got %#v", send, get, recv)
+			}
+		}
+	}
+
+	input := d.WaitKey(0, 50)
+	if input != -1 {
+		t.Errorf("Expected timeout, got %d / %X", input, input)
+	} else {
+		t.Logf("Ok! Buffer should be empty!  -1 (timeout)")
+	}
+
+	server.Close()
+
+	hungup := d.WaitKey(1, 0)
+	if hungup != -2 {
+		t.Errorf("Expected -2 (hangup), got %d", hungup)
+	}
+
+	if !d.Disconnected {
+		t.Errorf("Disconnected flag shows: %t (should be true)", d.Disconnected)
+	}
+
+	client.Close()
+
+}