@@ -2,13 +2,18 @@ package mongodb_test
2
2
3
3
import (
4
4
"context"
5
+ "errors"
6
+ "sync"
7
+ "sync/atomic"
5
8
"testing"
6
9
"time"
7
10
8
11
"github.com/google/uuid"
9
12
"github.com/plgd-dev/hub/v2/certificate-authority/store"
10
13
"github.com/plgd-dev/hub/v2/certificate-authority/test"
14
+ "github.com/stretchr/testify/assert"
11
15
"github.com/stretchr/testify/require"
16
+ "golang.org/x/exp/maps"
12
17
)
13
18
14
19
func TestUpdateRevocationList (t * testing.T ) {
@@ -179,8 +184,64 @@ func TestUpdateRevocationList(t *testing.T) {
179
184
}
180
185
}
181
186
182
- func TestParallelUpdateRevocationList (* testing.T ) {
183
- // TODO: run 10 parallel updates, they all should eventually succeed
187
+ func TestParallelUpdateRevocationList (t * testing.T ) {
188
+ s , cleanUpStore := test .NewMongoStore (t )
189
+ defer cleanUpStore ()
190
+
191
+ ctx , cancel := context .WithTimeout (context .Background (), time .Second * 30 )
192
+ defer cancel ()
193
+
194
+ issuerID := uuid .NewString ()
195
+ count := 10
196
+ certificates := make (map [int ]* store.RevocationListCertificate )
197
+ for i := range count {
198
+ certificates [i ] = test .GetCertificate (i , time .Now (), time .Now ().Add (time .Hour ))
199
+ }
200
+
201
+ var failed atomic.Bool
202
+ failed .Store (false )
203
+ var wg sync.WaitGroup
204
+ wg .Add (10 )
205
+ for i := range count {
206
+ go func (index int ) {
207
+ defer wg .Done ()
208
+ cert , ok := certificates [index ]
209
+ assert .True (t , ok )
210
+ var err error
211
+ for range 100 { // parallel execution should eventually succeed in cases when we get duplicate _id and
212
+ q := & store.UpdateRevocationListQuery {
213
+ IssuerID : issuerID ,
214
+ RevokedCertificates : []* store.RevocationListCertificate {cert },
215
+ }
216
+ _ , err = s .UpdateRevocationList (ctx , q )
217
+ if errors .Is (err , store .ErrDuplicateID ) || errors .Is (err , store .ErrNotFound ) {
218
+ continue
219
+ }
220
+ if err == nil {
221
+ break
222
+ }
223
+ failed .Store (true )
224
+ assert .NoError (t , err )
225
+ }
226
+ assert .NoError (t , err )
227
+ }(i )
228
+ }
229
+ wg .Wait ()
230
+ require .False (t , failed .Load ())
231
+
232
+ rl , err := s .GetLatestIssuedOrIssueRevocationList (ctx , issuerID , time .Hour )
233
+ require .NoError (t , err )
234
+
235
+ require .NotEmpty (t , rl .IssuedAt )
236
+ require .NotEmpty (t , rl .ValidUntil )
237
+ expected := & store.RevocationList {
238
+ Id : issuerID ,
239
+ Number : "1" ,
240
+ IssuedAt : rl .IssuedAt ,
241
+ ValidUntil : rl .ValidUntil ,
242
+ Certificates : maps .Values (certificates ),
243
+ }
244
+ test .CheckRevocationList (t , expected , rl , true )
184
245
}
185
246
186
247
func TestGetRevocationList (t * testing.T ) {
0 commit comments