cluster/identd/ident: add basic ident protocol server

This adds an ident protocol server and tests for it.

Change-Id: I830f85faa7dce4220bd7001635b20e88b4a8b417
diff --git a/cluster/identd/ident/response_test.go b/cluster/identd/ident/response_test.go
index e768d46..3ef5137 100644
--- a/cluster/identd/ident/response_test.go
+++ b/cluster/identd/ident/response_test.go
@@ -59,3 +59,84 @@
 		}
 	}
 }
+
+// TestResponseEncode exercises the encode method of Response.
+func TestResponseEncode(t *testing.T) {
+	for i, te := range []struct {
+		r    *Response
+		want string
+	}{
+		/// Standard features
+		// 0: simple error
+		{&Response{
+			ServerPort: 123,
+			ClientPort: 234,
+			Error:      InvalidPort,
+		}, "123,234:ERROR:INVALID-PORT\r\n"},
+		// 1: simple response, stripped US-ASCII
+		{&Response{
+			ServerPort: 123,
+			ClientPort: 234,
+			Ident: &IdentResponse{
+				OperatingSystem: "UNIX",
+				UserID:          "q3k",
+			},
+		}, "123,234:USERID:UNIX:q3k\r\n"},
+		// 2: simple response, stripped US-ASCII
+		{&Response{
+			ServerPort: 123,
+			ClientPort: 234,
+			Ident: &IdentResponse{
+				OperatingSystem: "UNIX",
+				CharacterSet:    "US-ASCII",
+				UserID:          "q3k",
+			},
+		}, "123,234:USERID:UNIX:q3k\r\n"},
+
+		/// Unusual features
+		// 3: unusual response
+		{&Response{
+			ServerPort: 123,
+			ClientPort: 234,
+			Ident: &IdentResponse{
+				OperatingSystem: "SUN",
+				CharacterSet:    "PETSCII",
+				UserID:          "q3k",
+			},
+		}, "123,234:USERID:SUN,PETSCII:q3k\r\n"},
+		// 4: non-standard error code
+		{&Response{
+			ServerPort: 123,
+			ClientPort: 234,
+			Error:      ErrorResponse("XNOMANA"),
+		}, "123,234:ERROR:XNOMANA\r\n"},
+
+		/// Errors
+		// 5: invalid error code (should return nil)
+		{&Response{
+			ServerPort: 123,
+			ClientPort: 234,
+			Error:      ErrorResponse("NOT ENOUGH MANA"),
+		}, ""},
+		// 6: no error/ident set (should return nil)
+		{&Response{
+			ServerPort: 123,
+			ClientPort: 234,
+		}, ""},
+		// 7: both error and ident set (should return nil)
+		{&Response{
+			ServerPort: 123,
+			ClientPort: 234,
+			Ident: &IdentResponse{
+				OperatingSystem: "UNIX",
+				CharacterSet:    "US-ASCII",
+				UserID:          "q3k",
+			},
+			Error: InvalidPort,
+		}, ""},
+	} {
+		if want, got := te.want, string(te.r.encode()); want != got {
+			t.Errorf("%d: wanted %q, got %q", i, want, got)
+		}
+	}
+}