~james/core

core/spindle/models/logger_cap_test.go -rw-r--r-- 2.3 KiB
452f17b7 — james chore(import): snapshot james.dad.town/core at f70c71c7696a 16 hours ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package models

import (
	"bufio"
	"encoding/json"
	"os"
	"path/filepath"
	"strings"
	"testing"
)

type capTestStep struct{}

func (capTestStep) Name() string    { return "build" }
func (capTestStep) Command() string { return "make" }
func (capTestStep) Kind() StepKind  { return StepKindUser }

func TestLogPastTheCapIsDroppedWithOneMarker(t *testing.T) {
	dir := t.TempDir()
	wid := testWorkflowId("capped")
	const maxBytes = 100 << 10
	logger, err := NewFileWorkflowLogger(dir, wid, nil, WithMaxLogBytes(maxBytes))
	if err != nil {
		t.Fatal(err)
	}
	out := logger.DataWriter(0, "stdout")
	line := []byte(strings.Repeat("x", 1000) + "\n")
	for range 1000 {
		if _, err := out.Write(line); err != nil {
			t.Fatal(err)
		}
	}
	if _, err := logger.EndWriter(0, capTestStep{}, StepOutcomeSuccess).Write(nil); err != nil {
		t.Fatal(err)
	}
	if err := logger.Close(); err != nil {
		t.Fatal(err)
	}

	path := filepath.Join(dir, wid.String()+".log")
	info, err := os.Stat(path)
	if err != nil {
		t.Fatal(err)
	}
	if info.Size() > maxBytes+4<<10 {
		t.Fatalf("log is %d bytes, want at most %d plus a line and a marker", info.Size(), maxBytes)
	}

	f, err := os.Open(path)
	if err != nil {
		t.Fatal(err)
	}
	defer f.Close()
	var markers int
	var last LogLine
	sc := bufio.NewScanner(f)
	for sc.Scan() {
		last = LogLine{}
		if err := json.Unmarshal(sc.Bytes(), &last); err != nil {
			t.Fatal(err)
		}
		if strings.HasPrefix(last.Content, "log truncated") {
			markers++
		}
	}
	if markers != 1 {
		t.Fatalf("%d truncation markers, want 1", markers)
	}
	if last.Kind != LogKindControl || last.StepStatus != StepStatusEnd {
		t.Fatalf("last line = %+v, want the step end line to survive the cap", last)
	}
}

func TestWriterDropsOutputPastTheCapWithoutBufferingIt(t *testing.T) {
	logger, err := NewFileWorkflowLogger(t.TempDir(), testWorkflowId("cap-buffer"), nil, WithMaxLogBytes(1<<10))
	if err != nil {
		t.Fatal(err)
	}
	w := logger.DataWriter(0, "stdout").(*dataWriter)
	if _, err := w.Write([]byte(strings.Repeat("x", 2<<10) + "\n")); err != nil {
		t.Fatal(err)
	}
	if _, err := w.Write([]byte("no newline yet")); err != nil {
		t.Fatal(err)
	}
	if len(w.pending) != 0 {
		t.Fatalf("%d bytes are buffered after the log hit its cap, want none", len(w.pending))
	}
	if err := logger.Close(); err != nil {
		t.Fatal(err)
	}
}