erste module drin.
zwischenstand: Architektur aktualisiert, TOFU implementiert,
This commit is contained in:
1 parent
9d5789c5d7
commit
c8df9d7651
41 files changed
+6455
-36
No files matched your search
@@ -0,0 +1,110 @@
|
||||
package stream
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
const evJSON = `{"event_id":"evt_1","timestamp":1,"type":"node_command","node_id":"n1","payload":{"action":"drain"}}`
|
||||
|
||||
var evWant = Event{
|
||||
ID: "evt_1",
|
||||
Timestamp: 1,
|
||||
Type: EventNodeCommand,
|
||||
NodeID: "n1",
|
||||
Payload: json.RawMessage(`{"action":"drain"}`),
|
||||
}
|
||||
|
||||
func decodeAll(t *testing.T, input string) ([]Event, error) {
|
||||
t.Helper()
|
||||
dec := NewDecoder(strings.NewReader(input))
|
||||
var out []Event
|
||||
for {
|
||||
ev, err := dec.Next()
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
out = append(out, ev)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecoder(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
want []Event
|
||||
}{
|
||||
{"einzelnes Event", "id: evt_1\nevent: node_command\ndata: " + evJSON + "\n\n", []Event{evWant}},
|
||||
{"Keepalives werden übersprungen", ":\n\n:\n\ndata: " + evJSON + "\n\n:\n\n", []Event{evWant}},
|
||||
{"CRLF-Zeilenenden", "id: evt_1\r\ndata: " + evJSON + "\r\n\r\n", []Event{evWant}},
|
||||
{"data ohne Leerzeichen", "data:" + evJSON + "\n\n", []Event{evWant}},
|
||||
{
|
||||
"mehrere data-Zeilen",
|
||||
"data: {\"event_id\":\"evt_1\",\"timestamp\":1,\ndata: \"type\":\"node_command\",\"node_id\":\"n1\",\ndata: \"payload\":{\"action\":\"drain\"}}\n\n",
|
||||
[]Event{evWant},
|
||||
},
|
||||
{"unbekannte Felder ignoriert", "retry: 1000\nfoo: bar\ndata: " + evJSON + "\n\n", []Event{evWant}},
|
||||
{"Leerzeilen ohne Daten", "\n\n\nevent: x\n\n", nil},
|
||||
{"zwei Events", "data: " + evJSON + "\n\ndata: " + evJSON + "\n\n", []Event{evWant, evWant}},
|
||||
{"leerer Stream", "", nil},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := decodeAll(t, tt.input)
|
||||
if !errors.Is(err, io.EOF) {
|
||||
t.Fatalf("erwartet io.EOF am Ende, bekommen %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Events weichen ab\n got: %+v\nwant: %+v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecoder_Errors(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
want error
|
||||
}{
|
||||
{"ungültiges JSON", "data: {kaputt\n\n", ErrInvalidEvent},
|
||||
{"Event ohne Typ", "data: {\"event_id\":\"evt_1\"}\n\n", ErrInvalidEvent},
|
||||
{"abgeschnittenes Event", "data: " + evJSON + "\n", io.ErrUnexpectedEOF},
|
||||
{"Zeile zu lang", "data: " + strings.Repeat("x", MaxEventSize+1) + "\n\n", ErrEventTooLarge},
|
||||
{"Summe der data-Zeilen zu lang", strings.Repeat("data: "+strings.Repeat("x", MaxEventSize/4)+"\n", 5) + "\n", ErrEventTooLarge},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
_, err := decodeAll(t, tt.input)
|
||||
if !errors.Is(err, tt.want) {
|
||||
t.Errorf("erwartet %v, bekommen %v", tt.want, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeDecodeRoundTrip(t *testing.T) {
|
||||
ev, err := NewEvent(EventServiceState, map[string]any{"labels": map[string]string{"traefik.enable": "true"}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ev.NodeID = "n1"
|
||||
frame, err := encode(ev)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !strings.HasPrefix(string(frame), "id: "+ev.ID+"\nevent: service_state\ndata: ") || !strings.HasSuffix(string(frame), "\n\n") {
|
||||
t.Errorf("unerwarteter SSE-Rahmen: %q", frame)
|
||||
}
|
||||
got, err := NewDecoder(strings.NewReader(string(frame))).Next()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(got, ev) {
|
||||
t.Errorf("Round-Trip weicht ab\n got: %+v\nwant: %+v", got, ev)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user