Skip to content

Commit 0d71f75

Browse files
committed
Merge remote-tracking branch 'origin/main' into CBG-4345-thread-err
2 parents 980589e + d8dd145 commit 0d71f75

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+717
-300
lines changed

auth/auth_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,6 @@ func TestRebuildChannelsError(t *testing.T) {
493493
auth := NewTestAuthenticator(t, dataStore, &computer, DefaultAuthenticatorOptions(base.TestCtx(t)))
494494
role, err := auth.NewRole("testRole2", ch.BaseSetOf(t, "explicit1"))
495495
require.NoError(t, err)
496-
assert.NoError(t, err)
497496
err = auth.Save(role)
498497
require.NoError(t, err)
499498

auth/collection_access_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ func TestUserCollectionAccess(t *testing.T) {
139139
require.ErrorIs(t, user.authorizeAllChannels(ch.BaseSetOf(t, "*")), errNotAllowedChannels)
140140
require.ErrorIs(t, user.authorizeAnyChannel(ch.BaseSetOf(t, "x")), errUnauthorized)
141141
require.ErrorIs(t, user.authorizeAnyChannel(ch.BaseSetOf(t, "*")), errUnauthorized)
142-
require.ErrorIs(t, user.authorizeAnyChannel(ch.BaseSetOf(t)), errUnauthorized) // Matching named collection checks
142+
require.ErrorIs(t, user.authorizeAnyChannel(ch.BaseSetOf(t)), errUnauthorized)
143+
// Matching named collection checks
143144
requireExpandCollectionWildCardChannels(t, user, scope, collection, []string{"*", "q"}, []string{"*"})
144145
requireCanSeeCollectionChannels(t, scope, collection, user, "x", "y", "z", "q", "*")
145146
require.NoError(t, user.authorizeAllCollectionChannels(scope, collection, ch.BaseSetOf(t, "x", "y")))

base/bucket.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -540,21 +540,25 @@ func RequireNoBucketTTL(ctx context.Context, b Bucket) error {
540540

541541
// GetSourceID returns the source ID for a bucket.
542542
func GetSourceID(ctx context.Context, bucket Bucket) (string, error) {
543-
// for rosmar bucket and testing, use the bucket name as the source ID to make it easier to identify the source
543+
bucketUUID, err := bucket.UUID()
544+
if err != nil {
545+
return "", err
546+
}
544547
gocbBucket, err := AsGocbV2Bucket(bucket)
545548
if err != nil {
546-
return bucket.GetName(), nil
549+
// for rosmar bucket and testing, use the bucket name as the source ID to make it easier to identify the source
550+
if underGoTest() {
551+
return bucket.GetName(), nil
552+
}
553+
serverUUID := ""
554+
return CreateEncodedSourceID(bucketUUID, serverUUID)
547555
}
548556

549557
// If not overwriting the source ID, for rosmar, serverUUID would be ""
550558
serverUUID, err := GetServerUUID(ctx, gocbBucket)
551559
if err != nil {
552560
return "", err
553561
}
554-
bucketUUID, err := bucket.UUID()
555-
if err != nil {
556-
return "", err
557-
}
558562
return CreateEncodedSourceID(bucketUUID, serverUUID)
559563
}
560564

base/logging_context_test.go

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ func requireLogIs(t testing.TB, s string, f func()) {
2525

2626
config := &ConsoleLoggerConfig{
2727
ColorEnabled: Ptr(false),
28+
FileLoggerConfig: FileLoggerConfig{
29+
Enabled: Ptr(true),
30+
},
2831
}
2932
tempLogger, err := NewConsoleLogger(TestCtx(t), false, config)
3033
require.NoError(t, err)
@@ -39,23 +42,11 @@ func requireLogIs(t testing.TB, s string, f func()) {
3942

4043
f()
4144

42-
var log string
43-
var originalLog string
44-
// Allow time for logs to be printed
45-
retry := func() (shouldRetry bool, err error, value any) {
46-
originalLog = b.String()
47-
if len(originalLog) < timestampLength {
48-
return false, nil, nil
49-
}
50-
log = originalLog[timestampLength:]
51-
if log == s {
52-
return false, nil, nil
53-
}
54-
return true, nil, nil
55-
}
56-
err, _ = RetryLoop(TestCtx(t), "wait for logs", retry, CreateSleeperFunc(10, 100))
57-
58-
require.NoError(t, err, "Console logs did not contain %q, got %q", s, originalLog)
45+
FlushLogBuffers()
46+
originalLog := b.String()
47+
require.GreaterOrEqual(t, len(originalLog), timestampLength, "%q is not a valid log line, needs to contain timestamp", originalLog)
48+
log := originalLog[timestampLength:]
49+
require.Equal(t, s, log)
5950
}
6051

6152
func RequireLogMessage(t testing.TB, ctx context.Context, expectedMessage string, logString string) {

base/stats.go

Lines changed: 95 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ const (
7676
StatUnitUnixTimestamp = "unix timestamp"
7777

7878
StatFormatInt = "int"
79+
StatFormatUint = "uint64"
7980
StatFormatFloat = "float"
8081
StatFormatDuration = "duration"
8182
StatFormatBool = "bool"
@@ -472,10 +473,10 @@ type CacheStats struct {
472473
// The highest sequence number cached.
473474
//
474475
// There may be skipped sequences lower than high_seq_cached.
475-
HighSeqCached *SgwIntStat `json:"high_seq_cached"`
476+
HighSeqCached *SgwUint64Stat `json:"high_seq_cached"`
476477
// The highest contiguous sequence number that has been cached.
477-
HighSeqStable *SgwIntStat `json:"high_seq_stable"`
478-
NonMobileIgnoredCount *SgwIntStat `json:"non_mobile_ignored_count"`
478+
HighSeqStable *SgwUint64Stat `json:"high_seq_stable"`
479+
NonMobileIgnoredCount *SgwIntStat `json:"non_mobile_ignored_count"`
479480
// The total number of active channels.
480481
NumActiveChannels *SgwIntStat `json:"num_active_channels"`
481482
// The total number of skipped sequences. This is a cumulative value.
@@ -606,9 +607,9 @@ type DatabaseStats struct {
606607
ReplicationBytesReceived *SgwIntStat `json:"replication_bytes_received"`
607608
ReplicationBytesSent *SgwIntStat `json:"replication_bytes_sent"`
608609
// The compaction_attachment_start_time.
609-
CompactionAttachmentStartTime *SgwIntStat `json:"compaction_attachment_start_time"`
610+
CompactionAttachmentStartTime *SgwUint64Stat `json:"compaction_attachment_start_time"`
610611
// The compaction_tombstone_start_time.
611-
CompactionTombstoneStartTime *SgwIntStat `json:"compaction_tombstone_start_time"`
612+
CompactionTombstoneStartTime *SgwUint64Stat `json:"compaction_tombstone_start_time"`
612613
// The total number of writes that left the document in a conflicted state. Includes new conflicts, and mutations that don’t resolve existing conflicts.
613614
ConflictWriteCount *SgwIntStat `json:"conflict_write_count"`
614615
// The total number of instances during import when the document cas had changed, but the document was not imported because the document body had not changed.
@@ -630,7 +631,7 @@ type DatabaseStats struct {
630631
// The total size of xattrs written (in bytes).
631632
DocWritesXattrBytes *SgwIntStat `json:"doc_writes_xattr_bytes"`
632633
// Highest sequence number seen on the caching DCP feed.
633-
HighSeqFeed *SgwIntStat `json:"high_seq_feed"`
634+
HighSeqFeed *SgwUint64Stat `json:"high_seq_feed"`
634635
// The number of attachments compacted
635636
NumAttachmentsCompacted *SgwIntStat `json:"num_attachments_compacted"`
636637
// The total number of documents read via Couchbase Lite 2.x replication since Sync Gateway node startup.
@@ -653,19 +654,19 @@ type DatabaseStats struct {
653654
// The total amount of bytes read over the public REST api
654655
PublicRestBytesRead *SgwIntStat `json:"public_rest_bytes_read"`
655656
// The value of the last sequence number assigned. Callers using Set should be holding a mutex or ensure concurrent updates to this value are otherwise safe.
656-
LastSequenceAssignedValue *SgwIntStat `json:"last_sequence_assigned_value"` // TODO: CBG-4579 - Replace with SgwUintStat stat
657+
LastSequenceAssignedValue *SgwUint64Stat `json:"last_sequence_assigned_value"`
657658
// The total number of sequence numbers assigned.
658-
SequenceAssignedCount *SgwIntStat `json:"sequence_assigned_count"`
659+
SequenceAssignedCount *SgwUint64Stat `json:"sequence_assigned_count"`
659660
// The total number of high sequence lookups.
660661
SequenceGetCount *SgwIntStat `json:"sequence_get_count"`
661662
// The total number of times the sequence counter document has been incremented.
662663
SequenceIncrCount *SgwIntStat `json:"sequence_incr_count"`
663664
// The total number of unused, reserved sequences released by Sync Gateway.
664-
SequenceReleasedCount *SgwIntStat `json:"sequence_released_count"`
665+
SequenceReleasedCount *SgwUint64Stat `json:"sequence_released_count"`
665666
// The value of the last sequence number reserved (which may not yet be assigned). Callers using Set should be holding a mutex or ensure concurrent updates to this value are otherwise safe.
666-
LastSequenceReservedValue *SgwIntStat `json:"last_sequence_reserved_value"` // TODO: CBG-4579 - Replace with SgwUintStat stat
667+
LastSequenceReservedValue *SgwUint64Stat `json:"last_sequence_reserved_value"`
667668
// The total number of sequences reserved by Sync Gateway.
668-
SequenceReservedCount *SgwIntStat `json:"sequence_reserved_count"`
669+
SequenceReservedCount *SgwUint64Stat `json:"sequence_reserved_count"`
669670
// The total number of corrupt sequences above the MaxSequencesToRelease threshold seen at the sequence allocator
670671
CorruptSequenceCount *SgwIntStat `json:"corrupt_sequence_count"`
671672
// The total number of warnings relating to the channel name size.
@@ -986,6 +987,11 @@ type SgwIntStat struct {
986987
AtomicInt
987988
}
988989

990+
type SgwUint64Stat struct {
991+
SgwStat
992+
atomic.Uint64
993+
}
994+
989995
// uint64 is used here because atomic ints do not support floats. Floats are encoded to uint64
990996
type SgwFloatStat struct {
991997
SgwStat
@@ -1079,6 +1085,74 @@ func (s *SgwIntStat) String() string {
10791085
return strconv.FormatInt(s.Value(), 10)
10801086
}
10811087

1088+
// NewUIntStat creates a uint64 stat. The stat is initialized to initialValue.
1089+
func NewUIntStat(subsystem, key, unit, description, addedVersion, deprecatedVersion, stability string, labelKeys, labelVals []string, statValueType prometheus.ValueType, initialValue uint64) (*SgwUint64Stat, error) {
1090+
stat, err := newSGWStat(subsystem, key, unit, description, addedVersion, deprecatedVersion, stability, labelKeys, labelVals, statValueType)
1091+
if err != nil {
1092+
return nil, err
1093+
}
1094+
1095+
wrappedStat := &SgwUint64Stat{
1096+
SgwStat: *stat,
1097+
}
1098+
1099+
wrappedStat.Set(initialValue)
1100+
1101+
if !SkipPrometheusStatsRegistration {
1102+
err := prometheus.Register(wrappedStat)
1103+
if err != nil {
1104+
return nil, err
1105+
}
1106+
}
1107+
1108+
return wrappedStat, nil
1109+
}
1110+
1111+
// FormatString returns a name of the stat type used for generating documentation.
1112+
func (s *SgwUint64Stat) FormatString() string {
1113+
return StatFormatUint
1114+
}
1115+
1116+
func (s *SgwUint64Stat) Describe(ch chan<- *prometheus.Desc) {
1117+
ch <- s.statDesc
1118+
}
1119+
1120+
// Collect satisfies the prometheus.Collector interface communicates the stat to prometheus. This is known to truncate to float64, which is the only format that prometheus can accept.
1121+
func (s *SgwUint64Stat) Collect(ch chan<- prometheus.Metric) {
1122+
ch <- prometheus.MustNewConstMetric(s.statDesc, s.statValueType, float64(s.Value()))
1123+
}
1124+
1125+
func (s *SgwUint64Stat) MarshalJSON() ([]byte, error) {
1126+
return []byte(strconv.FormatUint(s.Value(), 10)), nil
1127+
}
1128+
1129+
func (s *SgwUint64Stat) String() string {
1130+
return strconv.FormatUint(s.Value(), 10)
1131+
}
1132+
1133+
// Set updates the existing value. This satisfies the AtomicUint interface but code can prefer SgwUint64Stat.Store to match atomic.Uint64.
1134+
func (s *SgwUint64Stat) Set(value uint64) {
1135+
s.Store(value)
1136+
}
1137+
1138+
func (s *SgwUint64Stat) SetIfMax(value uint64) {
1139+
for {
1140+
cur := s.Load()
1141+
if cur >= value {
1142+
return
1143+
}
1144+
1145+
if s.CompareAndSwap(cur, value) {
1146+
return
1147+
}
1148+
}
1149+
}
1150+
1151+
// Value returns the value. This satisfies the AtomicUint interface but new code should prefer SgwUint64Stat.Load to match atomic.Uint64 interface.
1152+
func (s *SgwUint64Stat) Value() uint64 {
1153+
return s.Load()
1154+
}
1155+
10821156
func NewFloatStat(subsystem, key, unit, description, addedVersion, deprecatedVersion, stability string, labelKeys, labelVals []string, statValueType prometheus.ValueType, initialValue float64) (*SgwFloatStat, error) {
10831157
stat, err := newSGWStat(subsystem, key, unit, description, addedVersion, deprecatedVersion, stability, labelKeys, labelVals, statValueType)
10841158
if err != nil {
@@ -1387,11 +1461,11 @@ func (d *DbStats) initCacheStats() error {
13871461
if err != nil {
13881462
return err
13891463
}
1390-
resUtil.HighSeqCached, err = NewIntStat(SubsystemCacheKey, "high_seq_cached", StatUnitNoUnits, HighSeqCachedDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0)
1464+
resUtil.HighSeqCached, err = NewUIntStat(SubsystemCacheKey, "high_seq_cached", StatUnitNoUnits, HighSeqCachedDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0)
13911465
if err != nil {
13921466
return err
13931467
}
1394-
resUtil.HighSeqStable, err = NewIntStat(SubsystemCacheKey, "high_seq_stable", StatUnitNoUnits, HighStableSeqCachedDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0)
1468+
resUtil.HighSeqStable, err = NewUIntStat(SubsystemCacheKey, "high_seq_stable", StatUnitNoUnits, HighStableSeqCachedDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0)
13951469
if err != nil {
13961470
return err
13971471
}
@@ -1684,11 +1758,11 @@ func (d *DbStats) initDatabaseStats() error {
16841758
if err != nil {
16851759
return err
16861760
}
1687-
resUtil.CompactionAttachmentStartTime, err = NewIntStat(SubsystemDatabaseKey, "compaction_attachment_start_time", StatUnitUnixTimestamp, CompactionAttachmentStartTimeDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.GaugeValue, 0)
1761+
resUtil.CompactionAttachmentStartTime, err = NewUIntStat(SubsystemDatabaseKey, "compaction_attachment_start_time", StatUnitUnixTimestamp, CompactionAttachmentStartTimeDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.GaugeValue, 0)
16881762
if err != nil {
16891763
return err
16901764
}
1691-
resUtil.CompactionTombstoneStartTime, err = NewIntStat(SubsystemDatabaseKey, "compaction_tombstone_start_time", StatUnitUnixTimestamp, CompactionTombstoneStartTimeDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.GaugeValue, 0)
1765+
resUtil.CompactionTombstoneStartTime, err = NewUIntStat(SubsystemDatabaseKey, "compaction_tombstone_start_time", StatUnitUnixTimestamp, CompactionTombstoneStartTimeDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.GaugeValue, 0)
16921766
if err != nil {
16931767
return err
16941768
}
@@ -1728,7 +1802,7 @@ func (d *DbStats) initDatabaseStats() error {
17281802
if err != nil {
17291803
return err
17301804
}
1731-
resUtil.HighSeqFeed, err = NewIntStat(SubsystemDatabaseKey, "high_seq_feed", StatUnitNoUnits, HighSeqFeedDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0)
1805+
resUtil.HighSeqFeed, err = NewUIntStat(SubsystemDatabaseKey, "high_seq_feed", StatUnitNoUnits, HighSeqFeedDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0)
17321806
if err != nil {
17331807
return err
17341808
}
@@ -1776,11 +1850,11 @@ func (d *DbStats) initDatabaseStats() error {
17761850
if err != nil {
17771851
return err
17781852
}
1779-
resUtil.SequenceAssignedCount, err = NewIntStat(SubsystemDatabaseKey, "sequence_assigned_count", StatUnitNoUnits, SequenceAssignedCountDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0)
1853+
resUtil.SequenceAssignedCount, err = NewUIntStat(SubsystemDatabaseKey, "sequence_assigned_count", StatUnitNoUnits, SequenceAssignedCountDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0)
17801854
if err != nil {
17811855
return err
17821856
}
1783-
resUtil.LastSequenceAssignedValue, err = NewIntStat(SubsystemDatabaseKey, "last_sequence_assigned_value", StatUnitNoUnits, LastSequenceAssignedValueDesc, StatAddedVersion3dot2dot4, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0)
1857+
resUtil.LastSequenceAssignedValue, err = NewUIntStat(SubsystemDatabaseKey, "last_sequence_assigned_value", StatUnitNoUnits, LastSequenceAssignedValueDesc, StatAddedVersion3dot2dot4, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0)
17841858
if err != nil {
17851859
return err
17861860
}
@@ -1792,15 +1866,15 @@ func (d *DbStats) initDatabaseStats() error {
17921866
if err != nil {
17931867
return err
17941868
}
1795-
resUtil.SequenceReleasedCount, err = NewIntStat(SubsystemDatabaseKey, "sequence_released_count", StatUnitNoUnits, SequenceReleasedCountDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0)
1869+
resUtil.SequenceReleasedCount, err = NewUIntStat(SubsystemDatabaseKey, "sequence_released_count", StatUnitNoUnits, SequenceReleasedCountDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0)
17961870
if err != nil {
17971871
return err
17981872
}
1799-
resUtil.SequenceReservedCount, err = NewIntStat(SubsystemDatabaseKey, "sequence_reserved_count", StatUnitNoUnits, SequenceReservedCountDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0)
1873+
resUtil.SequenceReservedCount, err = NewUIntStat(SubsystemDatabaseKey, "sequence_reserved_count", StatUnitNoUnits, SequenceReservedCountDesc, StatAddedVersion3dot0dot0, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0)
18001874
if err != nil {
18011875
return err
18021876
}
1803-
resUtil.LastSequenceReservedValue, err = NewIntStat(SubsystemDatabaseKey, "last_sequence_reserved_value", StatUnitNoUnits, LastSequenceReservedValueDesc, StatAddedVersion3dot2dot4, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0)
1877+
resUtil.LastSequenceReservedValue, err = NewUIntStat(SubsystemDatabaseKey, "last_sequence_reserved_value", StatUnitNoUnits, LastSequenceReservedValueDesc, StatAddedVersion3dot2dot4, StatDeprecatedVersionNotDeprecated, StatStabilityCommitted, labelKeys, labelVals, prometheus.CounterValue, 0)
18041878
if err != nil {
18051879
return err
18061880
}

base/util.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ func RetryLoop[T any](ctx context.Context, description string, worker RetryWorke
476476
} else if errors.Is(ctxErr, context.DeadlineExceeded) {
477477
verb = "timed out"
478478
}
479-
return fmt.Errorf("Retry loop for %v %s based on context: %w", description, verb, ctxErr), *new(T)
479+
return fmt.Errorf("Retry loop for %v %s based on context: %w", description, verb, context.Cause(ctx)), *new(T)
480480
case <-time.After(time.Millisecond * time.Duration(sleepMs)):
481481
}
482482

base/util_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,29 @@ func TestRetryLoopContextCancellation(t *testing.T) {
239239
}()
240240
err, _ := RetryLoop(ctx, t.Name(), worker, CreateIndefiniteMaxDoublingSleeperFunc(10, 100))
241241
require.ErrorContains(t, err, "canceled based on context")
242+
require.ErrorIs(t, err, context.Canceled)
243+
require.Equal(t, ctx.Err(), context.Canceled)
244+
}
245+
246+
func TestRetryLoopContextCancellationWithCause(t *testing.T) {
247+
var invoked atomic.Bool
248+
worker := func() (shouldRetry bool, err error, value any) {
249+
invoked.Store(true)
250+
return true, nil, nil
251+
}
252+
253+
ctx, cancelFunc := context.WithCancelCause(TestCtx(t))
254+
255+
cause := errors.New("this specific issue")
256+
go func() {
257+
require.Eventually(t, func() bool { return invoked.Load() == true }, 10*time.Second, 50*time.Millisecond)
258+
cancelFunc(cause)
259+
}()
260+
err, _ := RetryLoop(ctx, t.Name(), worker, CreateIndefiniteMaxDoublingSleeperFunc(10, 100))
261+
require.ErrorContains(t, err, "Retry loop for TestRetryLoopContextCancellationWithCause canceled based on context: this specific issue")
262+
require.Equal(t, ctx.Err(), context.Canceled)
263+
require.ErrorIs(t, err, cause)
264+
require.NotErrorIs(t, err, context.Canceled)
242265
}
243266

244267
func TestRetryLoopContextDeadline(t *testing.T) {
@@ -253,6 +276,8 @@ func TestRetryLoopContextDeadline(t *testing.T) {
253276

254277
err, _ := RetryLoop(ctx, t.Name(), worker, CreateIndefiniteMaxDoublingSleeperFunc(10, 100))
255278
require.ErrorContains(t, err, "timed out based on context")
279+
require.ErrorIs(t, err, context.DeadlineExceeded)
280+
require.ErrorIs(t, ctx.Err(), context.DeadlineExceeded)
256281
}
257282

258283
func TestSyncSourceFromURL(t *testing.T) {

base/util_testing.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,3 +1011,8 @@ func RequireXattrNotFound(t testing.TB, dataStore sgbucket.DataStore, docID stri
10111011
require.Error(t, err, fmt.Sprintf("Expected xattr %q to not be found on document %q but has contents %s", xattrName, docID, xattrs[xattrName]))
10121012
RequireXattrNotFoundError(t, err)
10131013
}
1014+
1015+
// underGoTest returns true if the tests are being run via 'go test'
1016+
func underGoTest() bool {
1017+
return testing.Testing()
1018+
}

0 commit comments

Comments
 (0)