github.com/docker/libcompose@v0.4.1-0.20210616120443-2a046c0bdbf2/project/project_test.go (about)

     1  package project
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"strings"
     7  	"testing"
     8  
     9  	"golang.org/x/net/context"
    10  
    11  	"github.com/docker/libcompose/config"
    12  	"github.com/docker/libcompose/project/options"
    13  	"github.com/docker/libcompose/yaml"
    14  	"github.com/stretchr/testify/assert"
    15  )
    16  
    17  type TestServiceFactory struct {
    18  	Counts map[string]int
    19  }
    20  
    21  type TestService struct {
    22  	factory *TestServiceFactory
    23  	name    string
    24  	config  *config.ServiceConfig
    25  	EmptyService
    26  	Count int
    27  }
    28  
    29  func (t *TestService) Config() *config.ServiceConfig {
    30  	return t.config
    31  }
    32  
    33  func (t *TestService) Name() string {
    34  	return t.name
    35  }
    36  
    37  func (t *TestService) Run(ctx context.Context, commandParts []string, opts options.Run) (int, error) {
    38  	return 0, nil
    39  }
    40  
    41  func (t *TestService) Create(ctx context.Context, options options.Create) error {
    42  	key := t.name + ".create"
    43  	t.factory.Counts[key] = t.factory.Counts[key] + 1
    44  	return nil
    45  }
    46  
    47  func (t *TestService) DependentServices() []ServiceRelationship {
    48  	return nil
    49  }
    50  
    51  func (t *TestServiceFactory) Create(project *Project, name string, serviceConfig *config.ServiceConfig) (Service, error) {
    52  	return &TestService{
    53  		factory: t,
    54  		config:  serviceConfig,
    55  		name:    name,
    56  	}, nil
    57  }
    58  
    59  func TestTwoCall(t *testing.T) {
    60  	factory := &TestServiceFactory{
    61  		Counts: map[string]int{},
    62  	}
    63  
    64  	p := NewProject(&Context{
    65  		ServiceFactory: factory,
    66  	}, nil, nil)
    67  	p.ServiceConfigs = config.NewServiceConfigs()
    68  	p.ServiceConfigs.Add("foo", &config.ServiceConfig{})
    69  
    70  	if err := p.Create(context.Background(), options.Create{}, "foo"); err != nil {
    71  		t.Fatal(err)
    72  	}
    73  
    74  	if err := p.Create(context.Background(), options.Create{}, "foo"); err != nil {
    75  		t.Fatal(err)
    76  	}
    77  
    78  	if factory.Counts["foo.create"] != 2 {
    79  		t.Fatal("Failed to create twice")
    80  	}
    81  }
    82  
    83  func TestGetServiceConfig(t *testing.T) {
    84  
    85  	p := NewProject(&Context{}, nil, nil)
    86  	p.ServiceConfigs = config.NewServiceConfigs()
    87  	fooService := &config.ServiceConfig{}
    88  	p.ServiceConfigs.Add("foo", fooService)
    89  
    90  	config, ok := p.GetServiceConfig("foo")
    91  	if !ok {
    92  		t.Fatal("Foo service not found")
    93  	}
    94  
    95  	if config != fooService {
    96  		t.Fatal("Incorrect Service Config returned")
    97  	}
    98  
    99  	config, ok = p.GetServiceConfig("unknown")
   100  	if ok {
   101  		t.Fatal("Found service incorrectly")
   102  	}
   103  
   104  	if config != nil {
   105  		t.Fatal("Incorrect Service Config returned")
   106  	}
   107  }
   108  
   109  func TestParseWithBadContent(t *testing.T) {
   110  	p := NewProject(&Context{
   111  		ComposeBytes: [][]byte{
   112  			[]byte("garbage"),
   113  		},
   114  	}, nil, nil)
   115  
   116  	err := p.Parse()
   117  	if err == nil {
   118  		t.Fatal("Should have failed parse")
   119  	}
   120  
   121  	if !strings.Contains(err.Error(), "cannot unmarshal !!str `garbage` into config.Config") {
   122  		t.Fatalf("Should have failed parse: %#v", err)
   123  	}
   124  }
   125  
   126  func TestParseWithGoodContent(t *testing.T) {
   127  	p := NewProject(&Context{
   128  		ComposeBytes: [][]byte{
   129  			[]byte("not-garbage:\n  image: foo"),
   130  		},
   131  	}, nil, nil)
   132  
   133  	err := p.Parse()
   134  	if err != nil {
   135  		t.Fatal(err)
   136  	}
   137  }
   138  
   139  func TestParseWithDefaultEnvironmentLookup(t *testing.T) {
   140  	p := NewProject(&Context{
   141  		ComposeBytes: [][]byte{
   142  			[]byte("not-garbage:\n  image: foo:${version}"),
   143  		},
   144  	}, nil, nil)
   145  
   146  	err := p.Parse()
   147  	if err != nil {
   148  		t.Fatal(err)
   149  	}
   150  }
   151  
   152  type TestEnvironmentLookup struct {
   153  }
   154  
   155  func (t *TestEnvironmentLookup) Lookup(key string, config *config.ServiceConfig) []string {
   156  	return []string{fmt.Sprintf("%s=X", key)}
   157  }
   158  
   159  func TestEnvironmentResolve(t *testing.T) {
   160  	factory := &TestServiceFactory{
   161  		Counts: map[string]int{},
   162  	}
   163  
   164  	p := NewProject(&Context{
   165  		ServiceFactory:    factory,
   166  		EnvironmentLookup: &TestEnvironmentLookup{},
   167  	}, nil, nil)
   168  	p.ServiceConfigs = config.NewServiceConfigs()
   169  	p.ServiceConfigs.Add("foo", &config.ServiceConfig{
   170  		Environment: yaml.MaporEqualSlice([]string{
   171  			"A",
   172  			"A=",
   173  			"A=B",
   174  		}),
   175  	})
   176  
   177  	service, err := p.CreateService("foo")
   178  	if err != nil {
   179  		t.Fatal(err)
   180  	}
   181  
   182  	if !reflect.DeepEqual(service.Config().Environment, yaml.MaporEqualSlice{"A=X", "A=", "A=B"}) {
   183  		t.Fatal("Invalid environment", service.Config().Environment)
   184  	}
   185  }
   186  
   187  func TestParseWithMultipleComposeFiles(t *testing.T) {
   188  	configOne := []byte(`
   189    multiple:
   190      image: tianon/true
   191      ports:
   192        - 8000`)
   193  
   194  	configTwo := []byte(`
   195    multiple:
   196      image: busybox
   197      container_name: multi
   198      ports:
   199        - 9000`)
   200  
   201  	configThree := []byte(`
   202    multiple:
   203      image: busybox
   204      mem_limit: "40m"
   205      memswap_limit: 40000000
   206      ports:
   207        - 10000`)
   208  
   209  	p := NewProject(&Context{
   210  		ComposeBytes: [][]byte{configOne, configTwo},
   211  	}, nil, nil)
   212  
   213  	err := p.Parse()
   214  
   215  	assert.Nil(t, err)
   216  
   217  	multipleConfig, _ := p.ServiceConfigs.Get("multiple")
   218  	assert.Equal(t, "busybox", multipleConfig.Image)
   219  	assert.Equal(t, "multi", multipleConfig.ContainerName)
   220  	assert.Equal(t, []string{"8000", "9000"}, multipleConfig.Ports)
   221  
   222  	p = NewProject(&Context{
   223  		ComposeBytes: [][]byte{configTwo, configOne},
   224  	}, nil, nil)
   225  
   226  	err = p.Parse()
   227  
   228  	assert.Nil(t, err)
   229  
   230  	multipleConfig, _ = p.ServiceConfigs.Get("multiple")
   231  	assert.Equal(t, "tianon/true", multipleConfig.Image)
   232  	assert.Equal(t, "multi", multipleConfig.ContainerName)
   233  	assert.Equal(t, []string{"9000", "8000"}, multipleConfig.Ports)
   234  
   235  	p = NewProject(&Context{
   236  		ComposeBytes: [][]byte{configOne, configTwo, configThree},
   237  	}, nil, nil)
   238  
   239  	err = p.Parse()
   240  
   241  	assert.Nil(t, err)
   242  
   243  	multipleConfig, _ = p.ServiceConfigs.Get("multiple")
   244  	assert.Equal(t, "busybox", multipleConfig.Image)
   245  	assert.Equal(t, "multi", multipleConfig.ContainerName)
   246  	assert.Equal(t, []string{"8000", "9000", "10000"}, multipleConfig.Ports)
   247  	assert.Equal(t, yaml.MemStringorInt(41943040), multipleConfig.MemLimit)
   248  	assert.Equal(t, yaml.MemStringorInt(40000000), multipleConfig.MemSwapLimit)
   249  }