2023-04-04 22:45:32 +00:00
|
|
|
package management
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"nhooyr.io/websocket"
|
|
|
|
|
|
|
|
"github.com/cloudflare/cloudflared/internal/test"
|
|
|
|
)
|
|
|
|
|
2023-04-11 16:54:28 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2023-04-04 22:45:32 +00:00
|
|
|
func TestIntoClientEvent_StartStreaming(t *testing.T) {
|
2023-04-11 16:54:28 +00:00
|
|
|
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},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2023-04-24 16:39:26 +00:00
|
|
|
{
|
|
|
|
name: "sampling filter",
|
|
|
|
expected: EventStartStreaming{
|
|
|
|
ClientEvent: ClientEvent{Type: StartStreaming},
|
|
|
|
Filters: &StreamingFilters{
|
|
|
|
Sampling: 0.5,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2023-04-11 16:54:28 +00:00
|
|
|
{
|
|
|
|
name: "level and events filters",
|
|
|
|
expected: EventStartStreaming{
|
|
|
|
ClientEvent: ClientEvent{Type: StartStreaming},
|
|
|
|
Filters: &StreamingFilters{
|
2023-04-24 16:39:26 +00:00
|
|
|
Level: infoLevel,
|
|
|
|
Events: []LogEventType{Cloudflared},
|
|
|
|
Sampling: 0.5,
|
2023-04-11 16:54:28 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
} {
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
})
|
2023-04-04 22:45:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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},
|
2023-04-06 18:30:42 +00:00
|
|
|
Logs: []*Log{
|
2023-04-04 22:45:32 +00:00
|
|
|
{
|
2023-04-06 18:30:42 +00:00
|
|
|
Time: time.Now().UTC().Format(time.RFC3339),
|
|
|
|
Event: HTTP,
|
|
|
|
Level: Info,
|
|
|
|
Message: "test",
|
2023-04-04 22:45:32 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
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, "")
|
|
|
|
}
|