mirror of
https://github.com/ProtonMail/proton-bridge.git
synced 2025-12-11 13:16:53 +00:00
Fix of all known flaky tests
This commit is contained in:
@ -45,6 +45,8 @@ lint:
|
|||||||
- branches
|
- branches
|
||||||
script:
|
script:
|
||||||
- make lint
|
- make lint
|
||||||
|
tags:
|
||||||
|
- medium
|
||||||
|
|
||||||
test:
|
test:
|
||||||
stage: test
|
stage: test
|
||||||
@ -60,6 +62,8 @@ test:
|
|||||||
- pass init `gpg --list-keys | grep "^ " | tail -1 | tr -d '[:space:]'`
|
- pass init `gpg --list-keys | grep "^ " | tail -1 | tr -d '[:space:]'`
|
||||||
# Then finally run the tests
|
# Then finally run the tests
|
||||||
- make test
|
- make test
|
||||||
|
tags:
|
||||||
|
- medium
|
||||||
|
|
||||||
test-integration:
|
test-integration:
|
||||||
stage: test
|
stage: test
|
||||||
|
|||||||
37
internal/imap/cache/cache_test.go
vendored
37
internal/imap/cache/cache_test.go
vendored
@ -18,7 +18,6 @@
|
|||||||
package cache
|
package cache
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@ -59,34 +58,34 @@ func TestClearOld(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestClearBig(t *testing.T) {
|
func TestClearBig(t *testing.T) {
|
||||||
msg := []byte("Test message")
|
r := require.New(t)
|
||||||
|
wantMessage := []byte("Test message")
|
||||||
|
|
||||||
nSize := 3
|
wantCacheSize := 3
|
||||||
cacheSizeLimit = nSize*len(msg) + 1
|
nTestMessages := wantCacheSize * wantCacheSize
|
||||||
cacheTimeLimit = int64(nSize * nSize * 2) // be sure the message will survive
|
cacheSizeLimit = wantCacheSize*len(wantMessage) + 1
|
||||||
|
cacheTimeLimit = int64(1 << 20) // be sure the message will survive
|
||||||
|
|
||||||
// It should have more than nSize items.
|
// It should never have more than nSize items.
|
||||||
for i := 0; i < nSize*nSize; i++ {
|
for i := 0; i < nTestMessages; i++ {
|
||||||
time.Sleep(1 * time.Millisecond)
|
time.Sleep(1 * time.Millisecond)
|
||||||
SaveMail(fmt.Sprintf("%s%d", testUID, i), msg, bs)
|
SaveMail(fmt.Sprintf("%s%d", testUID, i), wantMessage, bs)
|
||||||
if len(mailCache) > nSize {
|
r.LessOrEqual(len(mailCache), wantCacheSize, "cache too big when %d", i)
|
||||||
t.Error("Number of items in cache should not be more than", nSize)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the oldest are deleted first.
|
// Check that the oldest are deleted first.
|
||||||
for i := 0; i < nSize*nSize; i++ {
|
for i := 0; i < nTestMessages; i++ {
|
||||||
iUID := fmt.Sprintf("%s%d", testUID, i)
|
iUID := fmt.Sprintf("%s%d", testUID, i)
|
||||||
reader, _ := LoadMail(iUID)
|
reader, _ := LoadMail(iUID)
|
||||||
if i < nSize*(nSize-1) && reader.Len() != 0 {
|
|
||||||
mail := mailCache[iUID]
|
mail := mailCache[iUID]
|
||||||
t.Error("LoadMail should return empty but have:", mail.data, iUID, mail.key.Timestamp)
|
|
||||||
}
|
|
||||||
stored := make([]byte, len(msg))
|
|
||||||
_, _ = reader.Read(stored)
|
|
||||||
|
|
||||||
if i >= nSize*(nSize-1) && !bytes.Equal(stored, msg) {
|
if i < (nTestMessages - wantCacheSize) {
|
||||||
t.Error("LoadMail returned wrong message:", stored, iUID)
|
r.Zero(reader.Len(), "LoadMail should return empty, but have %s for %s time %d ", string(mail.data), iUID, mail.key.Timestamp)
|
||||||
|
} else {
|
||||||
|
stored := make([]byte, len(wantMessage))
|
||||||
|
_, err := reader.Read(stored)
|
||||||
|
r.NoError(err)
|
||||||
|
r.Equal(wantMessage, stored, "LoadMail returned wrong message: %s for %s time %d", stored, iUID, mail.key.Timestamp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,7 +24,6 @@ import (
|
|||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -54,10 +53,10 @@ func TestEventLoopProcessMoreEvents(t *testing.T) {
|
|||||||
}, nil),
|
}, nil),
|
||||||
)
|
)
|
||||||
m.newStoreNoEvents(true)
|
m.newStoreNoEvents(true)
|
||||||
m.client.EXPECT().ListMessages(gomock.Any()).Return([]*pmapi.Message{}, 0, nil).AnyTimes()
|
|
||||||
|
|
||||||
// Event loop runs in goroutine and will be stopped by deferred mock clearing.
|
// Event loop runs in goroutine started during store creation (newStoreNoEvents).
|
||||||
go m.store.eventLoop.start()
|
// Force to run the next event.
|
||||||
|
m.store.eventLoop.pollNow()
|
||||||
|
|
||||||
// More events are processed right away.
|
// More events are processed right away.
|
||||||
require.Eventually(t, func() bool {
|
require.Eventually(t, func() bool {
|
||||||
@ -78,13 +77,15 @@ func TestEventLoopUpdateMessageFromLoop(t *testing.T) {
|
|||||||
subject := "old subject"
|
subject := "old subject"
|
||||||
newSubject := "new subject"
|
newSubject := "new subject"
|
||||||
|
|
||||||
// First sync will add message with old subject to database.
|
m.newStoreNoEvents(true, &pmapi.Message{
|
||||||
m.client.EXPECT().GetMessage("msg1").Return(&pmapi.Message{
|
|
||||||
ID: "msg1",
|
ID: "msg1",
|
||||||
Subject: subject,
|
Subject: subject,
|
||||||
}, nil)
|
})
|
||||||
// Event will update the subject.
|
|
||||||
m.client.EXPECT().GetEvent("latestEventID").Return(&pmapi.Event{
|
eventReceived := make(chan struct{})
|
||||||
|
m.client.EXPECT().GetEvent("latestEventID").DoAndReturn(func(eventID string) (*pmapi.Event, error) {
|
||||||
|
defer close(eventReceived)
|
||||||
|
return &pmapi.Event{
|
||||||
EventID: "event1",
|
EventID: "event1",
|
||||||
Messages: []*pmapi.EventMessage{{
|
Messages: []*pmapi.EventMessage{{
|
||||||
EventItem: pmapi.EventItem{
|
EventItem: pmapi.EventItem{
|
||||||
@ -96,20 +97,22 @@ func TestEventLoopUpdateMessageFromLoop(t *testing.T) {
|
|||||||
Subject: &newSubject,
|
Subject: &newSubject,
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
}, nil)
|
}, nil
|
||||||
|
})
|
||||||
|
|
||||||
m.newStoreNoEvents(true)
|
// Event loop runs in goroutine started during store creation (newStoreNoEvents).
|
||||||
|
// Force to run the next event.
|
||||||
|
m.store.eventLoop.pollNow()
|
||||||
|
|
||||||
// Event loop runs in goroutine and will be stopped by deferred mock clearing.
|
select {
|
||||||
go m.store.eventLoop.start()
|
case <-eventReceived:
|
||||||
|
case <-time.After(5 * time.Second):
|
||||||
|
require.Fail(t, "latestEventID was not processed")
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
msg, err := m.store.getMessageFromDB("msg1")
|
||||||
assert.Eventually(t, func() bool {
|
|
||||||
var msg *pmapi.Message
|
|
||||||
msg, err = m.store.getMessageFromDB("msg1")
|
|
||||||
return err == nil && msg.Subject == newSubject
|
|
||||||
}, time.Second, 10*time.Millisecond)
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, newSubject, msg.Subject)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEventLoopUpdateMessage(t *testing.T) {
|
func TestEventLoopUpdateMessage(t *testing.T) {
|
||||||
|
|||||||
@ -18,11 +18,12 @@
|
|||||||
package store
|
package store
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sync"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
storemocks "github.com/ProtonMail/proton-bridge/internal/store/mocks"
|
storemocks "github.com/ProtonMail/proton-bridge/internal/store/mocks"
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
||||||
@ -89,7 +90,7 @@ func initMocks(tb testing.TB) (*mocksForStore, func()) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mocks *mocksForStore) newStoreNoEvents(combinedMode bool) { //nolint[unparam]
|
func (mocks *mocksForStore) newStoreNoEvents(combinedMode bool, msgs ...*pmapi.Message) { //nolint[unparam]
|
||||||
mocks.user.EXPECT().ID().Return("userID").AnyTimes()
|
mocks.user.EXPECT().ID().Return("userID").AnyTimes()
|
||||||
mocks.user.EXPECT().IsConnected().Return(true)
|
mocks.user.EXPECT().IsConnected().Return(true)
|
||||||
mocks.user.EXPECT().IsCombinedAddressMode().Return(combinedMode)
|
mocks.user.EXPECT().IsCombinedAddressMode().Return(combinedMode)
|
||||||
@ -102,20 +103,19 @@ func (mocks *mocksForStore) newStoreNoEvents(combinedMode bool) { //nolint[unpar
|
|||||||
})
|
})
|
||||||
mocks.client.EXPECT().ListLabels()
|
mocks.client.EXPECT().ListLabels()
|
||||||
mocks.client.EXPECT().CountMessages("")
|
mocks.client.EXPECT().CountMessages("")
|
||||||
mocks.client.EXPECT().GetEvent(gomock.Any()).
|
|
||||||
Return(&pmapi.Event{
|
|
||||||
EventID: "latestEventID",
|
|
||||||
}, nil).AnyTimes()
|
|
||||||
|
|
||||||
// We want to wait until first sync has finished.
|
// Call to get latest event ID and then to process first event.
|
||||||
firstSyncWaiter := sync.WaitGroup{}
|
mocks.client.EXPECT().GetEvent("").Return(&pmapi.Event{
|
||||||
firstSyncWaiter.Add(1)
|
EventID: "firstEventID",
|
||||||
mocks.client.EXPECT().
|
}, nil)
|
||||||
ListMessages(gomock.Any()).
|
mocks.client.EXPECT().GetEvent("firstEventID").Return(&pmapi.Event{
|
||||||
DoAndReturn(func(*pmapi.MessagesFilter) ([]*pmapi.Message, int, error) {
|
EventID: "latestEventID",
|
||||||
firstSyncWaiter.Done()
|
}, nil)
|
||||||
return []*pmapi.Message{}, 0, nil
|
|
||||||
})
|
mocks.client.EXPECT().ListMessages(gomock.Any()).Return(msgs, len(msgs), nil).AnyTimes()
|
||||||
|
for _, msg := range msgs {
|
||||||
|
mocks.client.EXPECT().GetMessage(msg.ID).Return(msg, nil).AnyTimes()
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
mocks.store, err = New(
|
mocks.store, err = New(
|
||||||
@ -128,6 +128,16 @@ func (mocks *mocksForStore) newStoreNoEvents(combinedMode bool) { //nolint[unpar
|
|||||||
)
|
)
|
||||||
require.NoError(mocks.tb, err)
|
require.NoError(mocks.tb, err)
|
||||||
|
|
||||||
// Wait for sync to finish.
|
// We want to wait until first sync has finished.
|
||||||
firstSyncWaiter.Wait()
|
require.Eventually(mocks.tb, func() bool {
|
||||||
|
for _, msg := range msgs {
|
||||||
|
_, err := mocks.store.getMessageFromDB(msg.ID)
|
||||||
|
if err != nil {
|
||||||
|
// To see in test result the latest error for debugging.
|
||||||
|
fmt.Println("Sync wait error:", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}, 5*time.Second, 10*time.Millisecond)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -85,7 +85,7 @@ func testTransferFrom(t *testing.T, rules transferRules, provider TargetProvider
|
|||||||
progress.finish()
|
progress.finish()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
maxWait := time.Duration(len(messages)) * time.Second
|
maxWait := time.Duration(len(messages)) * 2 * time.Second
|
||||||
a.Eventually(t, func() bool {
|
a.Eventually(t, func() bool {
|
||||||
return progress.updateCh == nil
|
return progress.updateCh == nil
|
||||||
}, maxWait, 10*time.Millisecond, "Waiting for imported messages timed out")
|
}, maxWait, 10*time.Millisecond, "Waiting for imported messages timed out")
|
||||||
|
|||||||
@ -20,8 +20,6 @@ package users
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
|
||||||
gomock "github.com/golang/mock/gomock"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
@ -31,12 +29,7 @@ func testNewUser(m mocks) *User {
|
|||||||
m.clientManager.EXPECT().GetClient("user").Return(m.pmapiClient).MinTimes(1)
|
m.clientManager.EXPECT().GetClient("user").Return(m.pmapiClient).MinTimes(1)
|
||||||
|
|
||||||
mockConnectedUser(m)
|
mockConnectedUser(m)
|
||||||
|
mockEventLoopNoAction(m)
|
||||||
gomock.InOrder(
|
|
||||||
m.pmapiClient.EXPECT().GetEvent("").Return(testPMAPIEvent, nil).MaxTimes(1),
|
|
||||||
m.pmapiClient.EXPECT().GetEvent(testPMAPIEvent.EventID).Return(testPMAPIEvent, nil).MaxTimes(1),
|
|
||||||
m.pmapiClient.EXPECT().ListMessages(gomock.Any()).Return([]*pmapi.Message{}, 0, nil).MaxTimes(1),
|
|
||||||
)
|
|
||||||
|
|
||||||
user, err := newUser(m.PanicHandler, "user", m.eventListener, m.credentialsStore, m.clientManager, m.storeMaker)
|
user, err := newUser(m.PanicHandler, "user", m.eventListener, m.credentialsStore, m.clientManager, m.storeMaker)
|
||||||
assert.NoError(m.t, err)
|
assert.NoError(m.t, err)
|
||||||
@ -53,12 +46,7 @@ func testNewUserForLogout(m mocks) *User {
|
|||||||
m.clientManager.EXPECT().GetClient("user").Return(m.pmapiClient).MinTimes(1)
|
m.clientManager.EXPECT().GetClient("user").Return(m.pmapiClient).MinTimes(1)
|
||||||
|
|
||||||
mockConnectedUser(m)
|
mockConnectedUser(m)
|
||||||
|
mockEventLoopNoAction(m)
|
||||||
gomock.InOrder(
|
|
||||||
m.pmapiClient.EXPECT().GetEvent("").Return(testPMAPIEvent, nil).MaxTimes(1),
|
|
||||||
m.pmapiClient.EXPECT().GetEvent(testPMAPIEvent.EventID).Return(testPMAPIEvent, nil).MaxTimes(1),
|
|
||||||
m.pmapiClient.EXPECT().ListMessages(gomock.Any()).Return([]*pmapi.Message{}, 0, nil).MaxTimes(1),
|
|
||||||
)
|
|
||||||
|
|
||||||
user, err := newUser(m.PanicHandler, "user", m.eventListener, m.credentialsStore, m.clientManager, m.storeMaker)
|
user, err := newUser(m.PanicHandler, "user", m.eventListener, m.credentialsStore, m.clientManager, m.storeMaker)
|
||||||
assert.NoError(m.t, err)
|
assert.NoError(m.t, err)
|
||||||
|
|||||||
@ -23,7 +23,6 @@ import (
|
|||||||
|
|
||||||
"github.com/ProtonMail/proton-bridge/internal/events"
|
"github.com/ProtonMail/proton-bridge/internal/events"
|
||||||
"github.com/ProtonMail/proton-bridge/internal/users/credentials"
|
"github.com/ProtonMail/proton-bridge/internal/users/credentials"
|
||||||
"github.com/ProtonMail/proton-bridge/pkg/pmapi"
|
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
@ -86,36 +85,6 @@ func TestNewUsersWithConnectedUserWithBadToken(t *testing.T) {
|
|||||||
checkUsersNew(t, m, []*credentials.Credentials{testCredentialsDisconnected})
|
checkUsersNew(t, m, []*credentials.Credentials{testCredentialsDisconnected})
|
||||||
}
|
}
|
||||||
|
|
||||||
func mockConnectedUser(m mocks) {
|
|
||||||
gomock.InOrder(
|
|
||||||
m.credentialsStore.EXPECT().Get("user").Return(testCredentials, nil),
|
|
||||||
|
|
||||||
m.credentialsStore.EXPECT().Get("user").Return(testCredentials, nil),
|
|
||||||
m.pmapiClient.EXPECT().AuthRefresh("token").Return(testAuthRefresh, nil),
|
|
||||||
|
|
||||||
m.pmapiClient.EXPECT().Unlock([]byte(testCredentials.MailboxPassword)).Return(nil),
|
|
||||||
|
|
||||||
// Set up mocks for store initialisation for the authorized user.
|
|
||||||
m.pmapiClient.EXPECT().ListLabels().Return([]*pmapi.Label{}, nil),
|
|
||||||
m.pmapiClient.EXPECT().CountMessages("").Return([]*pmapi.MessagesCount{}, nil),
|
|
||||||
m.pmapiClient.EXPECT().Addresses().Return([]*pmapi.Address{testPMAPIAddress}),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// mockAuthUpdate simulates users calling UpdateAuthToken on the given user.
|
|
||||||
// This would normally be done by users when it receives an auth from the ClientManager,
|
|
||||||
// but as we don't have a full users instance here, we do this manually.
|
|
||||||
func mockAuthUpdate(user *User, token string, m mocks) {
|
|
||||||
gomock.InOrder(
|
|
||||||
m.credentialsStore.EXPECT().UpdateToken("user", ":"+token).Return(nil),
|
|
||||||
m.credentialsStore.EXPECT().Get("user").Return(credentialsWithToken(token), nil),
|
|
||||||
)
|
|
||||||
|
|
||||||
user.updateAuthToken(refreshWithToken(token))
|
|
||||||
|
|
||||||
waitForEvents()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNewUsersWithConnectedUser(t *testing.T) {
|
func TestNewUsersWithConnectedUser(t *testing.T) {
|
||||||
m := initMocks(t)
|
m := initMocks(t)
|
||||||
defer m.ctrl.Finish()
|
defer m.ctrl.Finish()
|
||||||
|
|||||||
@ -284,10 +284,37 @@ func TestClearData(t *testing.T) {
|
|||||||
func mockEventLoopNoAction(m mocks) {
|
func mockEventLoopNoAction(m mocks) {
|
||||||
// Set up mocks for starting the store's event loop (in store.New).
|
// Set up mocks for starting the store's event loop (in store.New).
|
||||||
// The event loop runs in another goroutine so this might happen at any time.
|
// The event loop runs in another goroutine so this might happen at any time.
|
||||||
|
m.pmapiClient.EXPECT().GetEvent("").Return(testPMAPIEvent, nil).AnyTimes()
|
||||||
|
m.pmapiClient.EXPECT().GetEvent(testPMAPIEvent.EventID).Return(testPMAPIEvent, nil).AnyTimes()
|
||||||
|
m.pmapiClient.EXPECT().ListMessages(gomock.Any()).Return([]*pmapi.Message{}, 0, nil).AnyTimes()
|
||||||
|
}
|
||||||
|
|
||||||
|
func mockConnectedUser(m mocks) {
|
||||||
gomock.InOrder(
|
gomock.InOrder(
|
||||||
m.pmapiClient.EXPECT().GetEvent("").Return(testPMAPIEvent, nil),
|
m.credentialsStore.EXPECT().Get("user").Return(testCredentials, nil),
|
||||||
m.pmapiClient.EXPECT().GetEvent(testPMAPIEvent.EventID).Return(testPMAPIEvent, nil),
|
|
||||||
// Set up mocks for performing the initial store sync.
|
m.credentialsStore.EXPECT().Get("user").Return(testCredentials, nil),
|
||||||
m.pmapiClient.EXPECT().ListMessages(gomock.Any()).Return([]*pmapi.Message{}, 0, nil),
|
m.pmapiClient.EXPECT().AuthRefresh("token").Return(testAuthRefresh, nil),
|
||||||
|
|
||||||
|
m.pmapiClient.EXPECT().Unlock([]byte(testCredentials.MailboxPassword)).Return(nil),
|
||||||
|
|
||||||
|
// Set up mocks for store initialisation for the authorized user.
|
||||||
|
m.pmapiClient.EXPECT().ListLabels().Return([]*pmapi.Label{}, nil),
|
||||||
|
m.pmapiClient.EXPECT().CountMessages("").Return([]*pmapi.MessagesCount{}, nil),
|
||||||
|
m.pmapiClient.EXPECT().Addresses().Return([]*pmapi.Address{testPMAPIAddress}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mockAuthUpdate simulates users calling UpdateAuthToken on the given user.
|
||||||
|
// This would normally be done by users when it receives an auth from the ClientManager,
|
||||||
|
// but as we don't have a full users instance here, we do this manually.
|
||||||
|
func mockAuthUpdate(user *User, token string, m mocks) {
|
||||||
|
gomock.InOrder(
|
||||||
|
m.credentialsStore.EXPECT().UpdateToken("user", ":"+token).Return(nil),
|
||||||
|
m.credentialsStore.EXPECT().Get("user").Return(credentialsWithToken(token), nil),
|
||||||
|
)
|
||||||
|
|
||||||
|
user.updateAuthToken(refreshWithToken(token))
|
||||||
|
|
||||||
|
waitForEvents()
|
||||||
|
}
|
||||||
|
|||||||
@ -43,7 +43,7 @@ func startServer() {
|
|||||||
_, _ = w.Write([]byte("OK"))
|
_, _ = w.Write([]byte("OK"))
|
||||||
})
|
})
|
||||||
http.HandleFunc("/timeout", func(w http.ResponseWriter, r *http.Request) {
|
http.HandleFunc("/timeout", func(w http.ResponseWriter, r *http.Request) {
|
||||||
time.Sleep(10 * time.Second)
|
time.Sleep(testRequestTimeout + time.Second) // Add extra second to be sure it will timeout.
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
_, _ = w.Write([]byte("OK"))
|
_, _ = w.Write([]byte("OK"))
|
||||||
})
|
})
|
||||||
|
|||||||
@ -15,3 +15,4 @@ Changelog [format](http://keepachangelog.com/en/1.0.0/)
|
|||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
* GODT-135 Support parameters in SMTP `FROM MAIL` command, such as `BODY=7BIT`, or empty value `FROM MAIL:<>` used by some clients.
|
* GODT-135 Support parameters in SMTP `FROM MAIL` command, such as `BODY=7BIT`, or empty value `FROM MAIL:<>` used by some clients.
|
||||||
|
* GODT-338 GODT-781 GODT-857 GODT-866 Flaky tests.
|
||||||
|
|||||||
Reference in New Issue
Block a user