mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-10-12 01:58:46 +02:00
feat(cli): port the log journal and network journal events to master
This commit is contained in:
1 parent
488065f6e8
commit
37b835c791
109 files changed
+17258
-905
No files matched your search
@@ -2,10 +2,14 @@ package cli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/Control-D-Inc/ctrld"
|
||||
)
|
||||
|
||||
func TestControlServer(t *testing.T) {
|
||||
@@ -52,3 +56,107 @@ func TestControlServer(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
// jsonStringTestPayload holds every byte class that a JSON string must escape
|
||||
// and splits a multi-byte character across the chunk boundary, so a chunk that
|
||||
// ends inside a character is covered.
|
||||
func jsonStringTestPayload() []byte {
|
||||
var payload bytes.Buffer
|
||||
payload.WriteString("quotes \" backslash \\ tab\t return\r newline\n")
|
||||
payload.Write([]byte{0x00, 0x01, 0x1f})
|
||||
for payload.Len() < jsonStringChunkSize-1 {
|
||||
payload.WriteByte('x')
|
||||
}
|
||||
payload.WriteString("é日本語 and an emoji 🙂\n")
|
||||
payload.WriteString("the tail after the boundary\n")
|
||||
return payload.Bytes()
|
||||
}
|
||||
|
||||
func Test_writeJSONString(t *testing.T) {
|
||||
payload := jsonStringTestPayload()
|
||||
var written bytes.Buffer
|
||||
|
||||
if err := writeJSONString(&written, bytes.NewReader(payload)); err != nil {
|
||||
t.Fatalf("writeJSONString: %v", err)
|
||||
}
|
||||
|
||||
var got string
|
||||
if err := json.Unmarshal(written.Bytes(), &got); err != nil {
|
||||
t.Fatalf("unmarshal %d bytes: %v", written.Len(), err)
|
||||
}
|
||||
if got != string(payload) {
|
||||
t.Fatalf("the round trip returned %d bytes, want the %d bytes of the payload", len(got), len(payload))
|
||||
}
|
||||
}
|
||||
|
||||
// newLogViewTestServer serves the log view handler of p on a temporary socket
|
||||
// and returns a client of it.
|
||||
func newLogViewTestServer(t *testing.T, p *prog) *controlClient {
|
||||
t.Helper()
|
||||
f, err := os.CreateTemp("", "")
|
||||
if err != nil {
|
||||
t.Fatalf("temporary socket: %v", err)
|
||||
}
|
||||
f.Close()
|
||||
t.Cleanup(func() { os.Remove(f.Name()) })
|
||||
s, err := newControlServer(f.Name())
|
||||
if err != nil {
|
||||
t.Fatalf("newControlServer: %v", err)
|
||||
}
|
||||
s.register(viewLogsPath, http.HandlerFunc(p.handleLogView))
|
||||
if err := s.start(); err != nil {
|
||||
t.Fatalf("start: %v", err)
|
||||
}
|
||||
t.Cleanup(func() { _ = s.stop() })
|
||||
return newControlClient(f.Name())
|
||||
}
|
||||
|
||||
func Test_logViewHandler(t *testing.T) {
|
||||
t.Run("answers the log as one JSON string", func(t *testing.T) {
|
||||
p := setupMemoryLogReaderTest(t)
|
||||
line := "a line with \"quotes\", a tab\there and 日本語\n"
|
||||
if _, err := p.internalLogWriter.Write([]byte(line)); err != nil {
|
||||
t.Fatalf("write the debug buffer: %v", err)
|
||||
}
|
||||
|
||||
resp, err := newLogViewTestServer(t, p).post(viewLogsPath, nil)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("post: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Fatalf("status = %d, want %d", resp.StatusCode, http.StatusOK)
|
||||
}
|
||||
if ct := resp.Header.Get("content-type"); ct != contentTypeJson {
|
||||
t.Fatalf("content type = %s, want %s", ct, contentTypeJson)
|
||||
}
|
||||
var view logViewResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&view); err != nil {
|
||||
t.Fatalf("decode the answer: %v", err)
|
||||
}
|
||||
if !strings.Contains(view.Data, line) {
|
||||
t.Fatalf("the answer holds %.64q, want the line %q in it", view.Data, line)
|
||||
}
|
||||
if !strings.Contains(view.Data, logWriterLogEndMarker) {
|
||||
t.Fatalf("the answer holds no log end marker: %.64q", view.Data)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("answers 301 without a log", func(t *testing.T) {
|
||||
origSilent, origCdUID := silent, cdUID
|
||||
t.Cleanup(func() { silent, cdUID = origSilent, origCdUID })
|
||||
silent, cdUID = false, ""
|
||||
p := &prog{cfg: &ctrld.Config{}}
|
||||
|
||||
resp, err := newLogViewTestServer(t, p).post(viewLogsPath, nil)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("post: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
if resp.StatusCode != http.StatusMovedPermanently {
|
||||
t.Fatalf("status = %d, want %d", resp.StatusCode, http.StatusMovedPermanently)
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user