Skip to content

Commit eac3e53

Browse files
committed
Added mutexes
Signed-off-by: Effi-S <effi.szt@gmail.com>
1 parent 312f321 commit eac3e53

4 files changed

Lines changed: 98 additions & 0 deletions

File tree

token/services/identity/deserializer/deserializer_test.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ package deserializer
99
import (
1010
"context"
1111
"errors"
12+
"sync"
1213
"testing"
1314

1415
"github.com/LFDT-Panurus/panurus/token/driver"
@@ -880,3 +881,76 @@ func TestTypedIdentityVerifierDeserializer(t *testing.T) {
880881
assert.Equal(t, 1, mockMatcherDeserializer.GetAuditInfoMatcherCallCount())
881882
})
882883
}
884+
885+
// TestDeserializerMultiplexConcurrency exercises the three deserializer
886+
// multiplexes under concurrent registration (map writes) and deserialization
887+
// (map reads). Without the internal mutex this reliably trips the race
888+
// detector or the runtime's fatal "concurrent map read and map write" check;
889+
// with it, the test runs clean. Run under `go test -race` for full coverage.
890+
func TestDeserializerMultiplexConcurrency(t *testing.T) {
891+
const (
892+
goroutines = 16
893+
iterations = 200
894+
)
895+
896+
signerMultiplex := NewTypedSignerDeserializerMultiplex()
897+
verifierMultiplex := NewTypedVerifierDeserializerMultiplex()
898+
eidrhDeserializer := NewEIDRHDeserializer()
899+
900+
// Pre-register a deserializer for the type the readers look up so the read
901+
// paths traverse the stored slice rather than bailing out on a miss.
902+
mockSigner := &drivermock.Signer{}
903+
signerDes := &identitydrivermock.TypedSignerDeserializer{}
904+
signerDes.DeserializeSignerReturns(mockSigner, nil)
905+
signerMultiplex.AddTypedSignerDeserializer(identity.Type(99), signerDes)
906+
907+
mockVerifier := &drivermock.Verifier{}
908+
verifierDes := &identitydrivermock.TypedVerifierDeserializer{}
909+
verifierDes.DeserializeVerifierReturns(mockVerifier, nil)
910+
verifierDes.RecipientsReturns([]driver.Identity{[]byte("recipient")}, nil)
911+
verifierDes.GetAuditInfoMatcherReturns(&drivermock.Matcher{}, nil)
912+
verifierDes.GetAuditInfoReturns([]byte("audit-info"), nil)
913+
verifierMultiplex.AddTypedVerifierDeserializer(identity.Type(99), verifierDes)
914+
915+
mockAuditInfo := &identitydrivermock.AuditInfo{}
916+
auditDes := &identitydrivermock.AuditInfoDeserializer{}
917+
auditDes.DeserializeAuditInfoReturns(mockAuditInfo, nil)
918+
eidrhDeserializer.AddDeserializer(identity.Type(99), auditDes)
919+
920+
typedID := createTypedIdentity(t, identity.Type(99), []byte("raw-identity"))
921+
provider := &drivermock.AuditInfoProvider{}
922+
923+
var wg sync.WaitGroup
924+
925+
// Writers: keep registering new deserializers concurrently.
926+
for range goroutines {
927+
wg.Go(func() {
928+
for range iterations {
929+
// Register under a distinct type so writers keep hammering the
930+
// same map concurrently without clobbering the entry the
931+
// readers rely on below.
932+
signerMultiplex.AddTypedSignerDeserializer(identity.Type(100), &identitydrivermock.TypedSignerDeserializer{})
933+
verifierMultiplex.AddTypedVerifierDeserializer(identity.Type(100), &identitydrivermock.TypedVerifierDeserializer{})
934+
eidrhDeserializer.AddDeserializer(identity.Type(100), &identitydrivermock.AuditInfoDeserializer{})
935+
}
936+
})
937+
}
938+
939+
// Readers: keep deserializing concurrently.
940+
for range goroutines {
941+
wg.Go(func() {
942+
ctx := context.Background()
943+
for range iterations {
944+
_, _ = signerMultiplex.DeserializeSigner(ctx, typedID)
945+
_, _ = verifierMultiplex.DeserializeVerifier(ctx, typedID)
946+
_, _ = verifierMultiplex.Recipients(typedID)
947+
_, _ = verifierMultiplex.GetAuditInfoMatcher(ctx, typedID, []byte("audit-info"))
948+
_ = verifierMultiplex.MatchIdentity(ctx, typedID, []byte("audit-info"))
949+
_, _ = verifierMultiplex.GetAuditInfo(ctx, typedID, provider)
950+
_, _, _ = eidrhDeserializer.GetEIDAndRH(ctx, typedID, []byte("audit-info"))
951+
}
952+
})
953+
}
954+
955+
wg.Wait()
956+
}

token/services/identity/deserializer/eidrh.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package deserializer
88

99
import (
1010
"context"
11+
"sync"
1112

1213
"github.com/LFDT-Panurus/panurus/token/driver"
1314
"github.com/LFDT-Panurus/panurus/token/services/identity"
@@ -17,6 +18,7 @@ import (
1718

1819
// EIDRHDeserializer returns enrollment IDs behind the owners of token
1920
type EIDRHDeserializer struct {
21+
mutex sync.RWMutex
2022
deserializers map[identity.Type]driver2.AuditInfoDeserializer
2123
}
2224

@@ -28,6 +30,8 @@ func NewEIDRHDeserializer() *EIDRHDeserializer {
2830
}
2931

3032
func (e *EIDRHDeserializer) AddDeserializer(typ identity.Type, d driver2.AuditInfoDeserializer) {
33+
e.mutex.Lock()
34+
defer e.mutex.Unlock()
3135
e.deserializers[typ] = d
3236
}
3337

@@ -69,7 +73,9 @@ func (e *EIDRHDeserializer) DeserializeAuditInfo(ctx context.Context, id driver.
6973
if err != nil {
7074
return nil, errors.Wrap(err, "failed to unmarshal to TypedIdentity")
7175
}
76+
e.mutex.RLock()
7277
d, ok := e.deserializers[si.Type]
78+
e.mutex.RUnlock()
7379
if !ok {
7480
return nil, errors.Errorf("no deserializer found for [%v]", si.Type)
7581
}

token/services/identity/deserializer/signer.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ package deserializer
99
import (
1010
"context"
1111
errors2 "errors"
12+
"sync"
1213

1314
"github.com/LFDT-Panurus/panurus/token/driver"
1415
"github.com/LFDT-Panurus/panurus/token/services/identity"
@@ -20,6 +21,7 @@ import (
2021
type TypedSignerDeserializer = idriver.TypedSignerDeserializer
2122

2223
type TypedSignerDeserializerMultiplex struct {
24+
mutex sync.RWMutex
2325
deserializers map[idriver.IdentityType][]TypedSignerDeserializer
2426
}
2527

@@ -28,6 +30,8 @@ func NewTypedSignerDeserializerMultiplex() *TypedSignerDeserializerMultiplex {
2830
}
2931

3032
func (v *TypedSignerDeserializerMultiplex) AddTypedSignerDeserializer(typ idriver.IdentityType, d idriver.TypedSignerDeserializer) {
33+
v.mutex.Lock()
34+
defer v.mutex.Unlock()
3135
_, ok := v.deserializers[typ]
3236
if !ok {
3337
v.deserializers[typ] = []TypedSignerDeserializer{d}
@@ -42,7 +46,9 @@ func (v *TypedSignerDeserializerMultiplex) DeserializeSigner(ctx context.Context
4246
if err != nil {
4347
return nil, errors.Wrap(err, "failed to unmarshal to TypedIdentity")
4448
}
49+
v.mutex.RLock()
4550
dess, ok := v.deserializers[si.Type]
51+
v.mutex.RUnlock()
4652
if !ok {
4753
return nil, errors.Errorf("no deserializer found for [%v]", si.Type)
4854
}

token/services/identity/deserializer/verifier.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ package deserializer
99
import (
1010
"context"
1111
errors2 "errors"
12+
"sync"
1213

1314
"github.com/LFDT-Panurus/panurus/token/driver"
1415
"github.com/LFDT-Panurus/panurus/token/services/identity"
@@ -23,6 +24,7 @@ var logger = logging.MustGetLogger()
2324
type TypedVerifierDeserializer = idriver.TypedVerifierDeserializer
2425

2526
type TypedVerifierDeserializerMultiplex struct {
27+
mutex sync.RWMutex
2628
deserializers map[idriver.IdentityType][]idriver.TypedVerifierDeserializer
2729
}
2830

@@ -31,6 +33,8 @@ func NewTypedVerifierDeserializerMultiplex() *TypedVerifierDeserializerMultiplex
3133
}
3234

3335
func (v *TypedVerifierDeserializerMultiplex) AddTypedVerifierDeserializer(typ idriver.IdentityType, d TypedVerifierDeserializer) {
36+
v.mutex.Lock()
37+
defer v.mutex.Unlock()
3438
_, ok := v.deserializers[typ]
3539
if !ok {
3640
v.deserializers[typ] = []TypedVerifierDeserializer{d}
@@ -45,7 +49,9 @@ func (v *TypedVerifierDeserializerMultiplex) DeserializeVerifier(ctx context.Con
4549
if err != nil {
4650
return nil, errors.Wrap(err, "failed to unmarshal to TypedIdentity")
4751
}
52+
v.mutex.RLock()
4853
dess, ok := v.deserializers[si.Type]
54+
v.mutex.RUnlock()
4955
if !ok {
5056
return nil, errors.Errorf("no deserializer found for [%v]", si.Type)
5157
}
@@ -73,7 +79,9 @@ func (v *TypedVerifierDeserializerMultiplex) Recipients(id driver.Identity) ([]d
7379
if err != nil {
7480
return nil, errors.Wrap(err, "failed to unmarshal to TypedIdentity")
7581
}
82+
v.mutex.RLock()
7683
dess, ok := v.deserializers[si.Type]
84+
v.mutex.RUnlock()
7785
if !ok {
7886
return nil, errors.Errorf("no deserializer found for [%v]", si.Type)
7987
}
@@ -110,7 +118,9 @@ func (v *TypedVerifierDeserializerMultiplex) GetAuditInfoMatcher(ctx context.Con
110118
}
111119

112120
func (v *TypedVerifierDeserializerMultiplex) getMatcher(ctx context.Context, idType idriver.IdentityType, id driver.Identity, auditInfo []byte) (driver.Matcher, error) {
121+
v.mutex.RLock()
113122
dess, ok := v.deserializers[idType]
123+
v.mutex.RUnlock()
114124
if !ok {
115125
return nil, errors.Errorf("no deserializer found for [%v]", idType)
116126
}
@@ -153,7 +163,9 @@ func (v *TypedVerifierDeserializerMultiplex) GetAuditInfo(ctx context.Context, i
153163
if err != nil {
154164
return nil, errors.Wrap(err, "failed to unmarshal to TypedIdentity")
155165
}
166+
v.mutex.RLock()
156167
dess, ok := v.deserializers[si.Type]
168+
v.mutex.RUnlock()
157169
if !ok {
158170
return nil, errors.Errorf("no deserializer found for [%v]", si.Type)
159171
}

0 commit comments

Comments
 (0)