Flamenco/internal/worker/upstream_buffer_test.go
Sybren A. Stüvel 1f8c2df919 Worker: skip sometimes-hanging unit test
The test can hang occasionally, and needs some love & attention. For now
I've done some patching to make it slightly better, but still disabled it
and added a `FIXME` note to it.
2022-06-27 11:30:35 +02:00

109 lines
3.0 KiB
Go

package worker
// SPDX-License-Identifier: GPL-3.0-or-later
import (
"context"
"errors"
"fmt"
"sync"
"testing"
"github.com/benbjohnson/clock"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
_ "modernc.org/sqlite"
"git.blender.org/flamenco/internal/worker/mocks"
"git.blender.org/flamenco/pkg/api"
)
type UpstreamBufferDBMocks struct {
client *mocks.MockFlamencoClient
clock *clock.Mock
}
func mockUpstreamBufferDB(t *testing.T, mockCtrl *gomock.Controller) (*UpstreamBufferDB, *UpstreamBufferDBMocks) {
mocks := UpstreamBufferDBMocks{
client: mocks.NewMockFlamencoClient(mockCtrl),
clock: clock.NewMock(),
}
ub, err := NewUpstreamBuffer(mocks.client, mocks.clock)
if err != nil {
t.Fatalf("unable to create upstream buffer: %v", err)
}
return ub, &mocks
}
// sqliteTestDBName returns a DSN for SQLite that separates tests from each
// other, but lets all connections made within the same test to connect to the
// same in-memory instance.
func sqliteTestDBName(t *testing.T) string {
return fmt.Sprintf("file:%s?mode=memory&cache=shared", t.Name())
}
func TestUpstreamBufferCloseUnopened(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
ub, _ := mockUpstreamBufferDB(t, mockCtrl)
err := ub.Close()
assert.NoError(t, err, "Closing without opening should be OK")
}
func TestUpstreamBufferManagerUnavailable(t *testing.T) {
// FIXME: This test is unreliable. The `wg.Wait()` function below can wait
// indefinitely in some situations, which points at a timing issue between
// various goroutines.
t.Skip("Skipping test, it is unreliable.")
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
ctx := context.Background()
ub, mocks := mockUpstreamBufferDB(t, mockCtrl)
assert.NoError(t, ub.OpenDB(ctx, sqliteTestDBName(t)))
// Send a task update without Manager available.
taskID := "3960dec4-978e-40ab-bede-bfa6428c6ebc"
update := api.TaskUpdateJSONRequestBody{
Activity: ptr("Testing da ünits"),
Log: ptr("¿Unicode logging should work?"),
TaskStatus: ptr(api.TaskStatusActive),
}
updateError := errors.New("mock manager unavailable")
managerCallFail := mocks.client.EXPECT().
TaskUpdateWithResponse(ctx, taskID, update).
Return(nil, updateError)
// Make it possible to wait for the queued item to be sent to the Manager.
wg := sync.WaitGroup{}
wg.Add(1)
mocks.client.EXPECT().
TaskUpdateWithResponse(ctx, taskID, update).
DoAndReturn(func(ctx context.Context, taskID string, body api.TaskUpdateJSONRequestBody, editors ...api.RequestEditorFn) (*api.TaskUpdateResponse, error) {
wg.Done()
return &api.TaskUpdateResponse{}, nil
}).
After(managerCallFail)
err := ub.SendTaskUpdate(ctx, taskID, update)
assert.NoError(t, err)
mocks.clock.Add(defaultUpstreamFlushInterval)
// Do the actual waiting.
wg.Wait()
// Queue should be empty now.
queueSize, err := ub.QueueSize()
assert.NoError(t, err)
assert.Equal(t, 0, queueSize)
assert.NoError(t, ub.Close())
}