mirror of
https://github.com/ScuroNeko/mtg.git
synced 2026-08-31 14:14:02 +03:00
fix: stabilize flaky CI tests
1. Add sync.Mutex to ScoutConnCollected to eliminate data race between Add()/MarkWrite() in readLoop and learn() iterating results. Introduce Snapshot() for safe read access. 2. Increase bloom filter test size from 500 to 100000 to prevent false negatives from random eviction in the stable bloom filter. 3. Use Require().NoError() in TestHTTPSRequest to prevent nil-pointer panic on resp.Body.Close() when the request fails. Fixes #425
This commit is contained in:
@@ -12,7 +12,7 @@ type StableBloomFilterTestSuite struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (suite *StableBloomFilterTestSuite) TestOp() {
|
func (suite *StableBloomFilterTestSuite) TestOp() {
|
||||||
filter := antireplay.NewStableBloomFilter(500, 0.001)
|
filter := antireplay.NewStableBloomFilter(100000, 0.001)
|
||||||
|
|
||||||
suite.False(filter.SeenBefore([]byte{1, 2, 3}))
|
suite.False(filter.SeenBefore([]byte{1, 2, 3}))
|
||||||
suite.False(filter.SeenBefore([]byte{4, 5, 6}))
|
suite.False(filter.SeenBefore([]byte{4, 5, 6}))
|
||||||
|
|||||||
@@ -61,7 +61,9 @@ func (s Scout) learn(ctx context.Context, url string) (ScoutResult, error) {
|
|||||||
client.CloseIdleConnections()
|
client.CloseIdleConnections()
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil || len(results.data) == 0 {
|
data, writeIndex := results.Snapshot()
|
||||||
|
|
||||||
|
if err != nil || len(data) == 0 {
|
||||||
return ScoutResult{}, err
|
return ScoutResult{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,14 +72,14 @@ func (s Scout) learn(ctx context.Context, url string) (ScoutResult, error) {
|
|||||||
// Compute inter-record durations (existing logic).
|
// Compute inter-record durations (existing logic).
|
||||||
lastTimestamp := time.Time{}
|
lastTimestamp := time.Time{}
|
||||||
|
|
||||||
for i, v := range results.data {
|
for i, v := range data {
|
||||||
if v.recordType != tls.TypeApplicationData {
|
if v.recordType != tls.TypeApplicationData {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if lastTimestamp.IsZero() {
|
if lastTimestamp.IsZero() {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
lastTimestamp = results.data[i-1].timestamp
|
lastTimestamp = data[i-1].timestamp
|
||||||
} else {
|
} else {
|
||||||
lastTimestamp = v.timestamp
|
lastTimestamp = v.timestamp
|
||||||
}
|
}
|
||||||
@@ -90,12 +92,12 @@ func (s Scout) learn(ctx context.Context, url string) (ScoutResult, error) {
|
|||||||
// Compute cert size: sum of ApplicationData payload between CCS and
|
// Compute cert size: sum of ApplicationData payload between CCS and
|
||||||
// the first client Write (which marks the end of server handshake).
|
// the first client Write (which marks the end of server handshake).
|
||||||
seenCCS := false
|
seenCCS := false
|
||||||
boundary := results.writeIndex
|
boundary := writeIndex
|
||||||
if boundary < 0 {
|
if boundary < 0 {
|
||||||
boundary = len(results.data)
|
boundary = len(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, v := range results.data {
|
for i, v := range data {
|
||||||
if i >= boundary {
|
if i >= boundary {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package doppel
|
package doppel
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ScoutConnCollectedPreallocSize = 100
|
ScoutConnCollectedPreallocSize = 100
|
||||||
@@ -13,23 +16,39 @@ type ScoutConnResult struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ScoutConnCollected struct {
|
type ScoutConnCollected struct {
|
||||||
|
mu sync.Mutex
|
||||||
data []ScoutConnResult
|
data []ScoutConnResult
|
||||||
writeIndex int // index at which client first wrote post-handshake data; -1 if not set
|
writeIndex int // index at which client first wrote post-handshake data; -1 if not set
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ScoutConnCollected) Add(record byte, payloadLen int) {
|
func (s *ScoutConnCollected) Add(record byte, payloadLen int) {
|
||||||
|
s.mu.Lock()
|
||||||
s.data = append(s.data, ScoutConnResult{
|
s.data = append(s.data, ScoutConnResult{
|
||||||
timestamp: time.Now(),
|
timestamp: time.Now(),
|
||||||
recordType: record,
|
recordType: record,
|
||||||
payloadLen: payloadLen,
|
payloadLen: payloadLen,
|
||||||
})
|
})
|
||||||
|
s.mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarkWrite records the current data length as the handshake boundary.
|
// MarkWrite records the current data length as the handshake boundary.
|
||||||
func (s *ScoutConnCollected) MarkWrite() {
|
func (s *ScoutConnCollected) MarkWrite() {
|
||||||
|
s.mu.Lock()
|
||||||
if s.writeIndex < 0 {
|
if s.writeIndex < 0 {
|
||||||
s.writeIndex = len(s.data)
|
s.writeIndex = len(s.data)
|
||||||
}
|
}
|
||||||
|
s.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Snapshot returns a copy of the collected data and the write index.
|
||||||
|
func (s *ScoutConnCollected) Snapshot() ([]ScoutConnResult, int) {
|
||||||
|
s.mu.Lock()
|
||||||
|
snapshot := make([]ScoutConnResult, len(s.data))
|
||||||
|
copy(snapshot, s.data)
|
||||||
|
writeIndex := s.writeIndex
|
||||||
|
s.mu.Unlock()
|
||||||
|
|
||||||
|
return snapshot, writeIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewScoutConnCollected() *ScoutConnCollected {
|
func NewScoutConnCollected() *ScoutConnCollected {
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ func (suite *ProxyTestSuite) TestHTTPSRequest() {
|
|||||||
addr := fmt.Sprintf("https://%s/headers", suite.ProxyAddress())
|
addr := fmt.Sprintf("https://%s/headers", suite.ProxyAddress())
|
||||||
|
|
||||||
resp, err := client.Get(addr) //nolint: noctx
|
resp, err := client.Get(addr) //nolint: noctx
|
||||||
suite.NoError(err)
|
suite.Require().NoError(err)
|
||||||
|
|
||||||
defer resp.Body.Close() //nolint: errcheck
|
defer resp.Body.Close() //nolint: errcheck
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user