Skip to content
This repository was archived by the owner on Jul 18, 2025. It is now read-only.

Commit b8bd316

Browse files
committed
Merge pull request #189 from vdemeester/unit-races
Enable race detector on unit tests… and fixes races
2 parents ff8b586 + 58f20e3 commit b8bd316

File tree

13 files changed

+197
-89
lines changed

13 files changed

+197
-89
lines changed

cli/app/app.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func WithProject(factory ProjectFactory, action ProjectAction) func(context *cli
4747
func ProjectPs(p *project.Project, c *cli.Context) {
4848
allInfo := project.InfoSet{}
4949
qFlag := c.Bool("q")
50-
for name := range p.Configs {
50+
for _, name := range p.Configs.Keys() {
5151
service, err := p.CreateService(name)
5252
if err != nil {
5353
logrus.Fatal(err)
@@ -147,7 +147,7 @@ func ProjectRun(p *project.Project, c *cli.Context) {
147147
serviceName := c.Args()[0]
148148
commandParts := c.Args()[1:]
149149

150-
if _, ok := p.Configs[serviceName]; !ok {
150+
if !p.Configs.Has(serviceName) {
151151
logrus.Fatalf("%s is not defined in the template", serviceName)
152152
}
153153

@@ -263,7 +263,7 @@ func ProjectScale(p *project.Project, c *cli.Context) {
263263
logrus.Fatalf("Invalid scale parameter: %v", err)
264264
}
265265

266-
if _, ok := p.Configs[name]; !ok {
266+
if !p.Configs.Has(name) {
267267
logrus.Fatalf("%s is not defined in the template", name)
268268
}
269269

docker/builder.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ func (d *DaemonBuilder) Build(imageName string, p *project.Project, service proj
9797
// CreateTar create a build context tar for the specified project and service name.
9898
func CreateTar(p *project.Project, name string) (io.ReadCloser, error) {
9999
// This code was ripped off from docker/api/client/build.go
100+
serviceConfig, _ := p.Configs.Get(name)
100101

101-
serviceConfig := p.Configs[name]
102102
root := serviceConfig.Build
103103
dockerfileName := filepath.Join(root, serviceConfig.Dockerfile)
104104

docker/container.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,7 @@ func (c *Container) populateAdditionalHostConfig(hostConfig *container.HostConfi
553553
links := map[string]string{}
554554

555555
for _, link := range c.service.DependentServices() {
556-
if _, ok := c.service.context.Project.Configs[link.Target]; !ok {
556+
if !c.service.context.Project.Configs.Has(link.Target) {
557557
continue
558558
}
559559

docker/convert.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,10 +198,10 @@ func Convert(c *project.ServiceConfig, ctx project.Context) (*container.Config,
198198
return config, hostConfig, nil
199199
}
200200

201-
func getVolumesFrom(volumesFrom []string, services map[string]*project.ServiceConfig, projectName string) ([]string, error) {
201+
func getVolumesFrom(volumesFrom []string, serviceConfigs *project.Configs, projectName string) ([]string, error) {
202202
volumes := []string{}
203203
for _, volumeFrom := range volumesFrom {
204-
if _, ok := services[volumeFrom]; ok {
204+
if serviceConfigs.Has(volumeFrom) {
205205
// It's a service - Use the first one
206206
name := fmt.Sprintf("%s_%s_1", projectName, volumeFrom)
207207
volumes = append(volumes, name)

project/listener.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func (d *defaultListener) start() {
7070
if event.ServiceName == "" {
7171
logf("Project [%s]: %s %s", d.project.Name, event.EventType, buffer.Bytes())
7272
} else {
73-
logf("[%d/%d] [%s]: %s %s", d.upCount, len(d.project.Configs), event.ServiceName, event.EventType, buffer.Bytes())
73+
logf("[%d/%d] [%s]: %s %s", d.upCount, d.project.Configs.Len(), event.ServiceName, event.EventType, buffer.Bytes())
7474
}
7575
}
7676
}

project/merge.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,9 @@ func mergeProject(p *Project, file string, bytes []byte) (map[string]*ServiceCon
5757
return nil, err
5858
}
5959

60-
if _, ok := p.Configs[name]; ok {
60+
if serviceConfig, ok := p.Configs.Get(name); ok {
6161
var rawExistingService RawService
62-
if err := utils.Convert(p.Configs[name], &rawExistingService); err != nil {
62+
if err := utils.Convert(serviceConfig, &rawExistingService); err != nil {
6363
return nil, err
6464
}
6565

project/project.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ type serviceAction func(service Service) error
3939
func NewProject(context *Context) *Project {
4040
p := &Project{
4141
context: context,
42-
Configs: make(map[string]*ServiceConfig),
42+
Configs: NewConfigs(),
4343
}
4444

4545
if context.LoggerFactory == nil {
@@ -87,7 +87,7 @@ func (p *Project) Parse() error {
8787
// CreateService creates a service with the specified name based. If there
8888
// is no config in the project for this service, it will return an error.
8989
func (p *Project) CreateService(name string) (Service, error) {
90-
existing, ok := p.Configs[name]
90+
existing, ok := p.Configs.Get(name)
9191
if !ok {
9292
return nil, fmt.Errorf("Failed to find service: %s", name)
9393
}
@@ -122,7 +122,7 @@ func (p *Project) CreateService(name string) (Service, error) {
122122
func (p *Project) AddConfig(name string, config *ServiceConfig) error {
123123
p.Notify(EventServiceAdd, name, nil)
124124

125-
p.Configs[name] = config
125+
p.Configs.Add(name, config)
126126
p.reload = append(p.reload, name)
127127

128128
return nil
@@ -415,7 +415,7 @@ func (p *Project) traverse(start bool, selected map[string]bool, wrappers map[st
415415
wrapperList := []string{}
416416

417417
if start {
418-
for name := range p.Configs {
418+
for _, name := range p.Configs.Keys() {
419419
wrapperList = append(wrapperList, name)
420420
}
421421
} else {

project/project_test.go

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,10 @@ func TestTwoCall(t *testing.T) {
5959
p := NewProject(&Context{
6060
ServiceFactory: factory,
6161
})
62-
p.Configs = map[string]*ServiceConfig{
63-
"foo": {},
62+
p.Configs = &Configs{
63+
m: map[string]*ServiceConfig{
64+
"foo": {},
65+
},
6466
}
6567

6668
if err := p.Create("foo"); err != nil {
@@ -137,13 +139,15 @@ func TestEnvironmentResolve(t *testing.T) {
137139
ServiceFactory: factory,
138140
EnvironmentLookup: &TestEnvironmentLookup{},
139141
})
140-
p.Configs = map[string]*ServiceConfig{
141-
"foo": {
142-
Environment: NewMaporEqualSlice([]string{
143-
"A",
144-
"A=",
145-
"A=B",
146-
}),
142+
p.Configs = &Configs{
143+
m: map[string]*ServiceConfig{
144+
"foo": {
145+
Environment: NewMaporEqualSlice([]string{
146+
"A",
147+
"A=",
148+
"A=B",
149+
}),
150+
},
147151
},
148152
}
149153

@@ -186,9 +190,10 @@ func TestParseWithMultipleComposeFiles(t *testing.T) {
186190

187191
assert.Nil(t, err)
188192

189-
assert.Equal(t, "busybox", p.Configs["multiple"].Image)
190-
assert.Equal(t, "multi", p.Configs["multiple"].ContainerName)
191-
assert.Equal(t, []string{"8000", "9000"}, p.Configs["multiple"].Ports)
193+
multipleConfig, _ := p.Configs.Get("multiple")
194+
assert.Equal(t, "busybox", multipleConfig.Image)
195+
assert.Equal(t, "multi", multipleConfig.ContainerName)
196+
assert.Equal(t, []string{"8000", "9000"}, multipleConfig.Ports)
192197

193198
p = NewProject(&Context{
194199
ComposeBytes: [][]byte{configTwo, configOne},
@@ -198,9 +203,10 @@ func TestParseWithMultipleComposeFiles(t *testing.T) {
198203

199204
assert.Nil(t, err)
200205

201-
assert.Equal(t, "tianon/true", p.Configs["multiple"].Image)
202-
assert.Equal(t, "multi", p.Configs["multiple"].ContainerName)
203-
assert.Equal(t, []string{"9000", "8000"}, p.Configs["multiple"].Ports)
206+
multipleConfig, _ = p.Configs.Get("multiple")
207+
assert.Equal(t, "tianon/true", multipleConfig.Image)
208+
assert.Equal(t, "multi", multipleConfig.ContainerName)
209+
assert.Equal(t, []string{"9000", "8000"}, multipleConfig.Ports)
204210

205211
p = NewProject(&Context{
206212
ComposeBytes: [][]byte{configOne, configTwo, configThree},
@@ -210,8 +216,9 @@ func TestParseWithMultipleComposeFiles(t *testing.T) {
210216

211217
assert.Nil(t, err)
212218

213-
assert.Equal(t, "busybox", p.Configs["multiple"].Image)
214-
assert.Equal(t, "multi", p.Configs["multiple"].ContainerName)
215-
assert.Equal(t, []string{"8000", "9000", "10000"}, p.Configs["multiple"].Ports)
216-
assert.Equal(t, int64(40000000), p.Configs["multiple"].MemLimit)
219+
multipleConfig, _ = p.Configs.Get("multiple")
220+
assert.Equal(t, "busybox", multipleConfig.Image)
221+
assert.Equal(t, "multi", multipleConfig.ContainerName)
222+
assert.Equal(t, []string{"8000", "9000", "10000"}, multipleConfig.Ports)
223+
assert.Equal(t, int64(40000000), multipleConfig.MemLimit)
217224
}

project/types.go

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package project
22

3-
import "fmt"
3+
import (
4+
"fmt"
5+
"sync"
6+
)
47

58
// EventType defines a type of libcompose event.
69
type EventType int
@@ -246,10 +249,64 @@ type ResourceLookup interface {
246249
ResolvePath(path, inFile string) string
247250
}
248251

252+
// NewConfigs initializes a new Configs struct
253+
func NewConfigs() *Configs {
254+
return &Configs{
255+
m: make(map[string]*ServiceConfig),
256+
}
257+
}
258+
259+
// Configs holds a concurrent safe map of ServiceConfig
260+
type Configs struct {
261+
m map[string]*ServiceConfig
262+
mu sync.RWMutex
263+
}
264+
265+
// Has checks if the config map has the specified name
266+
func (c *Configs) Has(name string) bool {
267+
c.mu.RLock()
268+
defer c.mu.RUnlock()
269+
_, ok := c.m[name]
270+
return ok
271+
}
272+
273+
// Get returns the config and the presence of the specified name
274+
func (c *Configs) Get(name string) (*ServiceConfig, bool) {
275+
c.mu.RLock()
276+
defer c.mu.RUnlock()
277+
service, ok := c.m[name]
278+
return service, ok
279+
}
280+
281+
// Add add the specifed config with the specified name
282+
func (c *Configs) Add(name string, service *ServiceConfig) {
283+
c.mu.Lock()
284+
c.m[name] = service
285+
c.mu.Unlock()
286+
}
287+
288+
// Len returns the len of the configs
289+
func (c *Configs) Len() int {
290+
c.mu.RLock()
291+
defer c.mu.RUnlock()
292+
return len(c.m)
293+
}
294+
295+
// Keys returns the names of the config
296+
func (c *Configs) Keys() []string {
297+
keys := []string{}
298+
c.mu.RLock()
299+
defer c.mu.RUnlock()
300+
for name := range c.m {
301+
keys = append(keys, name)
302+
}
303+
return keys
304+
}
305+
249306
// Project holds libcompose project information.
250307
type Project struct {
251308
Name string
252-
Configs map[string]*ServiceConfig
309+
Configs *Configs
253310
Files []string
254311
ReloadCallback func() error
255312
context *Context

project/utils.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func GetContainerFromIpcLikeConfig(p *Project, conf string) string {
6161
return ""
6262
}
6363

64-
if _, ok := p.Configs[name]; ok {
64+
if p.Configs.Has(name) {
6565
return name
6666
}
6767
return ""

0 commit comments

Comments
 (0)