cluster/identd/ident: add basic ident protocol client

This is the first pass at an ident protocol client. In the end, we want
to implement an ident protocol server for our in-cluster identd, but
starting out with a client helps me getting familiar with the protocol,
and will allow the server implementation to be tested against the
client.

Change-Id: Ic37b84577321533bab2f2fbf7fb53409a5defb95
diff --git a/cluster/identd/ident/response_test.go b/cluster/identd/ident/response_test.go
new file mode 100644
index 0000000..e768d46
--- /dev/null
+++ b/cluster/identd/ident/response_test.go
@@ -0,0 +1,61 @@
+package ident
+
+import (
+	"testing"
+
+	"github.com/go-test/deep"
+)
+
+// TestResponseDecode exercises the response decode implementation.
+func TestResponseDecode(t *testing.T) {
+	for i, te := range []struct {
+		data string
+		want *Response
+	}{
+		// 0: Everything okay, server returned error.
+		{"123, 234 : ERROR : INVALID-PORT", &Response{
+			ServerPort: 123,
+			ClientPort: 234,
+			Error:      InvalidPort,
+		}},
+		// 1: Everything okay, server returned error but also added some weird
+		// whitespace.
+		{" 123\t ,234  :ERROR:  NO-USER   ", &Response{
+			ServerPort: 123,
+			ClientPort: 234,
+			Error:      NoUser,
+		}},
+		// 2: Everything okay, server returned a simple ident response.
+		{"123,234 : USERID : UNIX :q3k", &Response{
+			ServerPort: 123,
+			ClientPort: 234,
+			Ident: &IdentResponse{
+				OperatingSystem: "UNIX",
+				CharacterSet:    "US-ASCII",
+				UserID:          "q3k",
+			},
+		}},
+		// 3: Everything okay, server returned an ident response with a
+		// charset.
+		{"123,234 : USERID : UNIX, PETSCII :q3k", &Response{
+			ServerPort: 123,
+			ClientPort: 234,
+			Ident: &IdentResponse{
+				OperatingSystem: "UNIX",
+				CharacterSet:    "PETSCII",
+				UserID:          "q3k",
+			},
+		}},
+	} {
+		res, err := decodeResponse([]byte(te.data))
+		if err != nil {
+			if te.want != nil {
+				t.Errorf("%d: wanted result, got err %v", i, err)
+			}
+		} else {
+			if diff := deep.Equal(te.want, res); diff != nil {
+				t.Errorf("%d: %s", i, diff)
+			}
+		}
+	}
+}