108 lines
3.2 KiB
Go
108 lines
3.2 KiB
Go
package ws
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"github.com/gorilla/websocket"
|
|
"github.com/openHPI/poseidon/internal/runner"
|
|
"github.com/openHPI/poseidon/pkg/dto"
|
|
"github.com/openHPI/poseidon/tests"
|
|
"github.com/stretchr/testify/mock"
|
|
)
|
|
|
|
func (s *MainTestSuite) TestRawToCodeOceanWriter() {
|
|
connectionMock, messages := buildConnectionMock(&s.MemoryLeakTestSuite)
|
|
proxyCtx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
output := NewCodeOceanOutputWriter(connectionMock, proxyCtx, cancel)
|
|
defer output.Close(nil)
|
|
<-messages // start messages
|
|
|
|
s.Run("StdOut", func() {
|
|
testMessage := "testStdOut"
|
|
_, err := output.StdOut().Write([]byte(testMessage))
|
|
s.Require().NoError(err)
|
|
|
|
expected, err := json.Marshal(struct {
|
|
Type string `json:"type"`
|
|
Data string `json:"data"`
|
|
}{string(dto.WebSocketOutputStdout), testMessage})
|
|
s.Require().NoError(err)
|
|
|
|
s.Equal(expected, <-messages)
|
|
})
|
|
|
|
s.Run("StdErr", func() {
|
|
testMessage := "testStdErr"
|
|
_, err := output.StdErr().Write([]byte(testMessage))
|
|
s.Require().NoError(err)
|
|
|
|
expected, err := json.Marshal(struct {
|
|
Type string `json:"type"`
|
|
Data string `json:"data"`
|
|
}{string(dto.WebSocketOutputStderr), testMessage})
|
|
s.Require().NoError(err)
|
|
|
|
s.Equal(expected, <-messages)
|
|
})
|
|
}
|
|
|
|
type sendExitInfoTestCase struct {
|
|
name string
|
|
info *runner.ExitInfo
|
|
message dto.WebSocketMessage
|
|
}
|
|
|
|
func (s *MainTestSuite) TestCodeOceanOutputWriter_SendExitInfo() {
|
|
testCases := []sendExitInfoTestCase{
|
|
{"Timeout", &runner.ExitInfo{Err: runner.ErrorRunnerInactivityTimeout},
|
|
dto.WebSocketMessage{Type: dto.WebSocketMetaTimeout}},
|
|
{"Error", &runner.ExitInfo{Err: websocket.ErrCloseSent},
|
|
dto.WebSocketMessage{Type: dto.WebSocketOutputError, Data: "Error executing the request"}},
|
|
// CodeOcean expects this exact string in case of a OOM Killed runner.
|
|
{"Specific data for OOM Killed runner", &runner.ExitInfo{Err: runner.ErrOOMKilled},
|
|
dto.WebSocketMessage{Type: dto.WebSocketOutputError, Data: "the allocation was OOM Killed"}},
|
|
{"Exit", &runner.ExitInfo{Code: 21},
|
|
dto.WebSocketMessage{Type: dto.WebSocketExit, ExitCode: 21}},
|
|
}
|
|
|
|
for _, test := range testCases {
|
|
s.Run(test.name, func() {
|
|
connectionMock, messages := buildConnectionMock(&s.MemoryLeakTestSuite)
|
|
proxyCtx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
output := NewCodeOceanOutputWriter(connectionMock, proxyCtx, cancel)
|
|
<-messages // start messages
|
|
|
|
output.Close(test.info)
|
|
expected, err := json.Marshal(test.message)
|
|
s.Require().NoError(err)
|
|
|
|
msg := <-messages
|
|
s.Equal(expected, msg)
|
|
|
|
<-messages // close message
|
|
})
|
|
}
|
|
}
|
|
|
|
func buildConnectionMock(s *tests.MemoryLeakTestSuite) (conn *ConnectionMock, messages <-chan []byte) {
|
|
s.T().Helper()
|
|
message := make(chan []byte)
|
|
connectionMock := &ConnectionMock{}
|
|
connectionMock.On("WriteMessage", mock.AnythingOfType("int"), mock.AnythingOfType("[]uint8")).
|
|
Run(func(args mock.Arguments) {
|
|
m, ok := args.Get(1).([]byte)
|
|
s.Require().True(ok)
|
|
select {
|
|
case <-s.TestCtx.Done():
|
|
case message <- m:
|
|
}
|
|
}).
|
|
Return(nil)
|
|
connectionMock.On("CloseHandler").Return(nil)
|
|
connectionMock.On("SetCloseHandler", mock.Anything).Return()
|
|
connectionMock.On("Close").Return(nil)
|
|
return connectionMock, message
|
|
}
|