cloudflared-mirror/management/events_test.go

248 lines
6.5 KiB
Go

package management
import (
"context"
"testing"
"time"
"github.com/stretchr/testify/require"
"nhooyr.io/websocket"
"github.com/cloudflare/cloudflared/internal/test"
)
var (
debugLevel *LogLevel
infoLevel *LogLevel
warnLevel *LogLevel
errorLevel *LogLevel
)
func init() {
// created here because we can't do a reference to a const enum, i.e. &Info
debugLevel := new(LogLevel)
*debugLevel = Debug
infoLevel := new(LogLevel)
*infoLevel = Info
warnLevel := new(LogLevel)
*warnLevel = Warn
errorLevel := new(LogLevel)
*errorLevel = Error
}
func TestIntoClientEvent_StartStreaming(t *testing.T) {
for _, test := range []struct {
name string
expected EventStartStreaming
}{
{
name: "no filters",
expected: EventStartStreaming{ClientEvent: ClientEvent{Type: StartStreaming}},
},
{
name: "level filter",
expected: EventStartStreaming{
ClientEvent: ClientEvent{Type: StartStreaming},
Filters: &StreamingFilters{
Level: infoLevel,
},
},
},
{
name: "events filter",
expected: EventStartStreaming{
ClientEvent: ClientEvent{Type: StartStreaming},
Filters: &StreamingFilters{
Events: []LogEventType{Cloudflared, HTTP},
},
},
},
{
name: "sampling filter",
expected: EventStartStreaming{
ClientEvent: ClientEvent{Type: StartStreaming},
Filters: &StreamingFilters{
Sampling: 0.5,
},
},
},
{
name: "level and events filters",
expected: EventStartStreaming{
ClientEvent: ClientEvent{Type: StartStreaming},
Filters: &StreamingFilters{
Level: infoLevel,
Events: []LogEventType{Cloudflared},
Sampling: 0.5,
},
},
},
} {
t.Run(test.name, func(t *testing.T) {
data, err := json.Marshal(test.expected)
require.NoError(t, err)
event := ClientEvent{}
err = json.Unmarshal(data, &event)
require.NoError(t, err)
event.event = data
ce, ok := IntoClientEvent[EventStartStreaming](&event, StartStreaming)
require.True(t, ok)
require.Equal(t, test.expected.ClientEvent, ce.ClientEvent)
if test.expected.Filters != nil {
f := ce.Filters
ef := test.expected.Filters
if ef.Level != nil {
require.Equal(t, *ef.Level, *f.Level)
}
require.ElementsMatch(t, ef.Events, f.Events)
}
})
}
}
func TestIntoClientEvent_StopStreaming(t *testing.T) {
event := ClientEvent{
Type: StopStreaming,
event: []byte(`{"type": "stop_streaming"}`),
}
ce, ok := IntoClientEvent[EventStopStreaming](&event, StopStreaming)
require.True(t, ok)
require.Equal(t, EventStopStreaming{ClientEvent: ClientEvent{Type: StopStreaming}}, *ce)
}
func TestIntoClientEvent_Invalid(t *testing.T) {
event := ClientEvent{
Type: UnknownClientEventType,
event: []byte(`{"type": "invalid"}`),
}
_, ok := IntoClientEvent[EventStartStreaming](&event, StartStreaming)
require.False(t, ok)
}
func TestIntoServerEvent_Logs(t *testing.T) {
event := ServerEvent{
Type: Logs,
event: []byte(`{"type": "logs"}`),
}
ce, ok := IntoServerEvent(&event, Logs)
require.True(t, ok)
require.Equal(t, EventLog{ServerEvent: ServerEvent{Type: Logs}}, *ce)
}
func TestIntoServerEvent_Invalid(t *testing.T) {
event := ServerEvent{
Type: UnknownServerEventType,
event: []byte(`{"type": "invalid"}`),
}
_, ok := IntoServerEvent(&event, Logs)
require.False(t, ok)
}
func TestReadServerEvent(t *testing.T) {
sentEvent := EventLog{
ServerEvent: ServerEvent{Type: Logs},
Logs: []*Log{
{
Time: time.Now().UTC().Format(time.RFC3339),
Event: HTTP,
Level: Info,
Message: "test",
},
},
}
client, server := test.WSPipe(nil, nil)
server.CloseRead(context.Background())
defer func() {
server.Close(websocket.StatusInternalError, "")
}()
go func() {
err := WriteEvent(server, context.Background(), &sentEvent)
require.NoError(t, err)
}()
event, err := ReadServerEvent(client, context.Background())
require.NoError(t, err)
require.Equal(t, sentEvent.Type, event.Type)
client.Close(websocket.StatusInternalError, "")
}
func TestReadServerEvent_InvalidWebSocketMessageType(t *testing.T) {
client, server := test.WSPipe(nil, nil)
server.CloseRead(context.Background())
defer func() {
server.Close(websocket.StatusInternalError, "")
}()
go func() {
err := server.Write(context.Background(), websocket.MessageBinary, []byte("test1234"))
require.NoError(t, err)
}()
_, err := ReadServerEvent(client, context.Background())
require.Error(t, err)
client.Close(websocket.StatusInternalError, "")
}
func TestReadServerEvent_InvalidMessageType(t *testing.T) {
sentEvent := ClientEvent{Type: ClientEventType(UnknownServerEventType)}
client, server := test.WSPipe(nil, nil)
server.CloseRead(context.Background())
defer func() {
server.Close(websocket.StatusInternalError, "")
}()
go func() {
err := WriteEvent(server, context.Background(), &sentEvent)
require.NoError(t, err)
}()
_, err := ReadServerEvent(client, context.Background())
require.ErrorIs(t, err, errInvalidMessageType)
client.Close(websocket.StatusInternalError, "")
}
func TestReadClientEvent(t *testing.T) {
sentEvent := EventStartStreaming{
ClientEvent: ClientEvent{Type: StartStreaming},
}
client, server := test.WSPipe(nil, nil)
client.CloseRead(context.Background())
defer func() {
client.Close(websocket.StatusInternalError, "")
}()
go func() {
err := WriteEvent(client, context.Background(), &sentEvent)
require.NoError(t, err)
}()
event, err := ReadClientEvent(server, context.Background())
require.NoError(t, err)
require.Equal(t, sentEvent.Type, event.Type)
server.Close(websocket.StatusInternalError, "")
}
func TestReadClientEvent_InvalidWebSocketMessageType(t *testing.T) {
client, server := test.WSPipe(nil, nil)
client.CloseRead(context.Background())
defer func() {
client.Close(websocket.StatusInternalError, "")
}()
go func() {
err := client.Write(context.Background(), websocket.MessageBinary, []byte("test1234"))
require.NoError(t, err)
}()
_, err := ReadClientEvent(server, context.Background())
require.Error(t, err)
server.Close(websocket.StatusInternalError, "")
}
func TestReadClientEvent_InvalidMessageType(t *testing.T) {
sentEvent := ClientEvent{Type: UnknownClientEventType}
client, server := test.WSPipe(nil, nil)
client.CloseRead(context.Background())
defer func() {
client.Close(websocket.StatusInternalError, "")
}()
go func() {
err := WriteEvent(client, context.Background(), &sentEvent)
require.NoError(t, err)
}()
_, err := ReadClientEvent(server, context.Background())
require.ErrorIs(t, err, errInvalidMessageType)
server.Close(websocket.StatusInternalError, "")
}