Add tests for codeOceanToRaw and null readers
The tests ensure the readers do not return when there is no data available.
This commit is contained in:
@ -16,11 +16,13 @@ import (
|
|||||||
"gitlab.hpi.de/codeocean/codemoon/poseidon/api/dto"
|
"gitlab.hpi.de/codeocean/codemoon/poseidon/api/dto"
|
||||||
"gitlab.hpi.de/codeocean/codemoon/poseidon/nomad"
|
"gitlab.hpi.de/codeocean/codemoon/poseidon/nomad"
|
||||||
"gitlab.hpi.de/codeocean/codemoon/poseidon/runner"
|
"gitlab.hpi.de/codeocean/codemoon/poseidon/runner"
|
||||||
|
"gitlab.hpi.de/codeocean/codemoon/poseidon/tests"
|
||||||
"gitlab.hpi.de/codeocean/codemoon/poseidon/tests/helpers"
|
"gitlab.hpi.de/codeocean/codemoon/poseidon/tests/helpers"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -305,8 +307,70 @@ func TestRawToCodeOceanWriter(t *testing.T) {
|
|||||||
assert.Equal(t, expected, message)
|
assert.Equal(t, expected, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCodeOceanToRawReaderReturnsOnlyAfterOneByteWasRead(t *testing.T) {
|
||||||
|
reader := newCodeOceanToRawReader(nil)
|
||||||
|
|
||||||
|
read := make(chan int)
|
||||||
|
go func() {
|
||||||
|
p := make([]byte, 10)
|
||||||
|
n, _ := reader.Read(p)
|
||||||
|
read <- n
|
||||||
|
}()
|
||||||
|
|
||||||
|
t.Run("Does not return immediately when there is no data", func(t *testing.T) {
|
||||||
|
assert.False(t, waitForChannel(read, tests.ShortTimeout))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Returns when there is data available", func(t *testing.T) {
|
||||||
|
reader.buffer <- byte(42)
|
||||||
|
assert.True(t, waitForChannel(read, tests.ShortTimeout))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCodeOceanToRawReaderReturnsOnlyAfterOneByteWasReadFromConnection(t *testing.T) {
|
||||||
|
messages := make(chan io.Reader)
|
||||||
|
|
||||||
|
connection := &webSocketConnectionMock{}
|
||||||
|
connection.On("WriteMessage", mock.AnythingOfType("int"), mock.AnythingOfType("[]uint8")).Return(nil)
|
||||||
|
connection.On("CloseHandler").Return(nil)
|
||||||
|
connection.On("SetCloseHandler", mock.Anything).Return()
|
||||||
|
call := connection.On("NextReader")
|
||||||
|
call.Run(func(_ mock.Arguments) {
|
||||||
|
call.Return(websocket.TextMessage, <-messages, nil)
|
||||||
|
})
|
||||||
|
|
||||||
|
reader := newCodeOceanToRawReader(connection)
|
||||||
|
cancel := reader.readInputLoop()
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
read := make(chan int)
|
||||||
|
message := make([]byte, 10)
|
||||||
|
go func() {
|
||||||
|
n, _ := reader.Read(message)
|
||||||
|
read <- n
|
||||||
|
}()
|
||||||
|
|
||||||
|
t.Run("Does not return immediately when there is no data", func(t *testing.T) {
|
||||||
|
assert.False(t, waitForChannel(read, tests.ShortTimeout))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Returns when there is data available", func(t *testing.T) {
|
||||||
|
messages <- strings.NewReader("Hello")
|
||||||
|
assert.True(t, waitForChannel(read, tests.ShortTimeout))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// --- Test suite specific test helpers ---
|
// --- Test suite specific test helpers ---
|
||||||
|
|
||||||
|
func waitForChannel(ch chan int, duration time.Duration) bool {
|
||||||
|
select {
|
||||||
|
case <-ch:
|
||||||
|
return true
|
||||||
|
case <-time.After(duration):
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func newNomadAllocationWithMockedApiClient(runnerId string) (r runner.Runner, mock *nomad.ExecutorAPIMock) {
|
func newNomadAllocationWithMockedApiClient(runnerId string) (r runner.Runner, mock *nomad.ExecutorAPIMock) {
|
||||||
mock = &nomad.ExecutorAPIMock{}
|
mock = &nomad.ExecutorAPIMock{}
|
||||||
r = runner.NewNomadJob(runnerId, mock)
|
r = runner.NewNomadJob(runnerId, mock)
|
||||||
|
@ -750,3 +750,19 @@ func (s *ExecuteCommandTestSuite) mockExecute(command interface{}, exitCode int,
|
|||||||
Run(runFunc).
|
Run(runFunc).
|
||||||
Return(exitCode, err)
|
Return(exitCode, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNullReaderDoesNotReturnImmediately(t *testing.T) {
|
||||||
|
reader := &nullReader{}
|
||||||
|
readerReturned := make(chan bool)
|
||||||
|
go func() {
|
||||||
|
p := make([]byte, 5)
|
||||||
|
_, _ = reader.Read(p)
|
||||||
|
close(readerReturned)
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-readerReturned:
|
||||||
|
t.Fatal("Read should not return immediately.")
|
||||||
|
case <-time.After(tests.ShortTimeout):
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package tests
|
package tests
|
||||||
|
|
||||||
import "errors"
|
import (
|
||||||
|
"errors"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
NonExistingIntegerID = 9999
|
NonExistingIntegerID = 9999
|
||||||
@ -21,6 +24,7 @@ const (
|
|||||||
AnotherRunnerID = AnotherJobID
|
AnotherRunnerID = AnotherJobID
|
||||||
DefaultExecutionID = "s0m3-3x3cu710n-1d"
|
DefaultExecutionID = "s0m3-3x3cu710n-1d"
|
||||||
DefaultMockID = "m0ck-1d"
|
DefaultMockID = "m0ck-1d"
|
||||||
|
ShortTimeout = 100 * time.Millisecond
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
Reference in New Issue
Block a user