1
0
Эх сурвалжийг харах

Merge pull request #9823 from ulyssessouza/add-codecov

Add Codecov
Ulysses Souza 3 жил өмнө
parent
commit
a6dd996988

+ 3 - 0
.github/workflows/ci.yml

@@ -177,6 +177,9 @@ jobs:
         if: ${{ matrix.mode == 'plugin' }}
         run: |
           make e2e-compose
+      -
+        name: Upload coverage to Codecov
+        uses: codecov/codecov-action@v3
       -
         name: Test standalone mode
         if: ${{ matrix.mode == 'standalone' }}

+ 1 - 0
.gitignore

@@ -1,2 +1,3 @@
 bin/
 /.vscode/
+coverage.out

+ 3 - 2
Makefile

@@ -33,7 +33,8 @@ ifeq ($(DETECTED_OS),Windows)
 	BINARY_EXT=.exe
 endif
 
-TEST_FLAGS?=
+TEST_COVERAGE_FLAGS = -race -coverprofile=coverage.out -covermode=atomic
+TEST_FLAGS?= -timeout 15m
 E2E_TEST?=
 ifeq ($(E2E_TEST),)
 else
@@ -61,7 +62,7 @@ install: binary
 .PHONY: e2e-compose
 e2e-compose: ## Run end to end local tests in plugin mode. Set E2E_TEST=TestName to run a single test
 	docker compose version
-	go test $(TEST_FLAGS) -count=1 ./pkg/e2e
+	go test $(TEST_FLAGS) $(TEST_COVERAGE_FLAGS) -count=1 ./pkg/e2e
 
 .PHONY: e2e-compose-standalone
 e2e-compose-standalone: ## Run End to end local tests in standalone mode. Set E2E_TEST=TestName to run a single test

+ 1 - 0
README.md

@@ -4,6 +4,7 @@
 [![PkgGoDev](https://img.shields.io/badge/go.dev-docs-007d9c?style=flat-square&logo=go&logoColor=white)](https://pkg.go.dev/github.com/docker/compose/v2)
 [![Build Status](https://img.shields.io/github/workflow/status/docker/compose/ci?label=ci&logo=github&style=flat-square)](https://github.com/docker/compose/actions?query=workflow%3Aci)
 [![Go Report Card](https://goreportcard.com/badge/github.com/docker/compose/v2?style=flat-square)](https://goreportcard.com/report/github.com/docker/compose/v2)
+[![Codecov](https://codecov.io/gh/docker/compose/branch/master/graph/badge.svg?token=HP3K4Y4ctu)](https://codecov.io/gh/docker/compose)
 
 ![Docker Compose](logo.png?raw=true "Docker Compose Logo")
 

+ 0 - 66
pkg/e2e/buffer.go

@@ -1,66 +0,0 @@
-/*
-   Copyright 2022 Docker Compose CLI authors
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-*/
-
-package e2e
-
-import (
-	"bytes"
-	"strings"
-	"sync"
-	"testing"
-	"time"
-
-	"github.com/stretchr/testify/require"
-)
-
-type lockedBuffer struct {
-	mu  sync.Mutex
-	buf bytes.Buffer
-}
-
-func (l *lockedBuffer) Read(p []byte) (n int, err error) {
-	l.mu.Lock()
-	defer l.mu.Unlock()
-	return l.buf.Read(p)
-}
-
-func (l *lockedBuffer) Write(p []byte) (n int, err error) {
-	l.mu.Lock()
-	defer l.mu.Unlock()
-	return l.buf.Write(p)
-}
-
-func (l *lockedBuffer) String() string {
-	l.mu.Lock()
-	defer l.mu.Unlock()
-	return l.buf.String()
-}
-
-func (l *lockedBuffer) RequireEventuallyContains(t testing.TB, v string) {
-	t.Helper()
-	var bufContents strings.Builder
-	require.Eventuallyf(t, func() bool {
-		l.mu.Lock()
-		defer l.mu.Unlock()
-		if _, err := l.buf.WriteTo(&bufContents); err != nil {
-			require.FailNowf(t, "Failed to copy from buffer",
-				"Error: %v", err)
-		}
-		return strings.Contains(bufContents.String(), v)
-	}, 5*time.Second, 20*time.Millisecond,
-		"Buffer did not contain %q\n============\n%s\n============",
-		v, &bufContents)
-}

+ 17 - 11
pkg/e2e/cancel_test.go

@@ -20,7 +20,7 @@
 package e2e
 
 import (
-	"bytes"
+	"context"
 	"fmt"
 	"os/exec"
 	"strings"
@@ -28,6 +28,7 @@ import (
 	"testing"
 	"time"
 
+	"github.com/docker/compose/v2/pkg/utils"
 	"gotest.tools/v3/assert"
 	"gotest.tools/v3/icmd"
 )
@@ -41,8 +42,12 @@ func TestComposeCancel(t *testing.T) {
 
 		// require a separate groupID from the process running tests, in order to simulate ctrl+C from a terminal.
 		// sending kill signal
-		cmd, stdout, stderr, err := StartWithNewGroupID(c.NewDockerComposeCmd(t, "-f", buildProjectPath, "build",
-			"--progress", "plain"))
+		stdout := &utils.SafeBuffer{}
+		stderr := &utils.SafeBuffer{}
+		cmd, err := StartWithNewGroupID(context.Background(),
+			c.NewDockerComposeCmd(t, "-f", buildProjectPath, "build", "--progress", "plain"),
+			stdout,
+			stderr)
 		assert.NilError(t, err)
 
 		c.WaitForCondition(t, func() (bool, string) {
@@ -65,15 +70,16 @@ func TestComposeCancel(t *testing.T) {
 	})
 }
 
-func StartWithNewGroupID(command icmd.Cmd) (*exec.Cmd, *bytes.Buffer, *bytes.Buffer, error) {
-	cmd := exec.Command(command.Command[0], command.Command[1:]...)
+func StartWithNewGroupID(ctx context.Context, command icmd.Cmd, stdout *utils.SafeBuffer, stderr *utils.SafeBuffer) (*exec.Cmd, error) {
+	cmd := exec.CommandContext(ctx, command.Command[0], command.Command[1:]...)
 	cmd.Env = command.Env
 	cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
-
-	var stdout bytes.Buffer
-	var stderr bytes.Buffer
-	cmd.Stdout = &stdout
-	cmd.Stderr = &stderr
+	if stdout != nil {
+		cmd.Stdout = stdout
+	}
+	if stderr != nil {
+		cmd.Stderr = stderr
+	}
 	err := cmd.Start()
-	return cmd, &stdout, &stderr, err
+	return cmd, err
 }

+ 15 - 21
pkg/e2e/up_test.go

@@ -26,6 +26,7 @@ import (
 	"testing"
 	"time"
 
+	"github.com/docker/compose/v2/pkg/utils"
 	"github.com/stretchr/testify/assert"
 	"github.com/stretchr/testify/require"
 	"gotest.tools/v3/icmd"
@@ -52,9 +53,6 @@ func TestUpDependenciesNotStopped(t *testing.T) {
 	reset()
 	t.Cleanup(reset)
 
-	ctx, cancel := context.WithCancel(context.Background())
-	defer cancel()
-
 	t.Log("Launching orphan container (background)")
 	c.RunDockerComposeCmd(t,
 		"-f=./fixtures/ups-deps-stop/orphan.yaml",
@@ -66,22 +64,18 @@ func TestUpDependenciesNotStopped(t *testing.T) {
 	RequireServiceState(t, c, "orphan", "running")
 
 	t.Log("Launching app container with implicit dependency")
-	var upOut lockedBuffer
-	var upCmd *exec.Cmd
-	go func() {
-		testCmd := c.NewDockerComposeCmd(t,
-			"-f=./fixtures/ups-deps-stop/compose.yaml",
-			"up",
-			"app",
-		)
-		cmd := exec.CommandContext(ctx, testCmd.Command[0], testCmd.Command[1:]...)
-		cmd.Env = testCmd.Env
-		cmd.Stdout = &upOut
-		cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
-
-		assert.NoError(t, cmd.Start(), "Failed to run compose up")
-		upCmd = cmd
-	}()
+	upOut := &utils.SafeBuffer{}
+	testCmd := c.NewDockerComposeCmd(t,
+		"-f=./fixtures/ups-deps-stop/compose.yaml",
+		"up",
+		"app",
+	)
+
+	ctx, cancel := context.WithCancel(context.Background())
+	defer cancel()
+
+	cmd, err := StartWithNewGroupID(ctx, testCmd, upOut, nil)
+	assert.NoError(t, err, "Failed to run compose up")
 
 	t.Log("Waiting for containers to be in running state")
 	upOut.RequireEventuallyContains(t, "hello app")
@@ -89,13 +83,13 @@ func TestUpDependenciesNotStopped(t *testing.T) {
 	RequireServiceState(t, c, "dependency", "running")
 
 	t.Log("Simulating Ctrl-C")
-	require.NoError(t, syscall.Kill(-upCmd.Process.Pid, syscall.SIGINT),
+	require.NoError(t, syscall.Kill(-cmd.Process.Pid, syscall.SIGINT),
 		"Failed to send SIGINT to compose up process")
 
 	time.AfterFunc(5*time.Second, cancel)
 
 	t.Log("Waiting for `compose up` to exit")
-	err := upCmd.Wait()
+	err = cmd.Wait()
 	if err != nil {
 		exitErr := err.(*exec.ExitError)
 		require.EqualValues(t, exitErr.ExitCode(), 130)

+ 78 - 0
pkg/utils/safebuffer.go

@@ -0,0 +1,78 @@
+/*
+   Copyright 2020 Docker Compose CLI authors
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package utils
+
+import (
+	"bytes"
+	"strings"
+	"sync"
+	"testing"
+	"time"
+
+	"github.com/stretchr/testify/require"
+)
+
+// SafeBuffer is a thread safe version of bytes.Buffer
+type SafeBuffer struct {
+	m sync.RWMutex
+	b bytes.Buffer
+}
+
+// Read is a thread safe version of bytes.Buffer::Read
+func (b *SafeBuffer) Read(p []byte) (n int, err error) {
+	b.m.RLock()
+	defer b.m.RUnlock()
+	return b.b.Read(p)
+}
+
+// Write is a thread safe version of bytes.Buffer::Write
+func (b *SafeBuffer) Write(p []byte) (n int, err error) {
+	b.m.Lock()
+	defer b.m.Unlock()
+	return b.b.Write(p)
+}
+
+// String is a thread safe version of bytes.Buffer::String
+func (b *SafeBuffer) String() string {
+	b.m.RLock()
+	defer b.m.RUnlock()
+	return b.b.String()
+}
+
+// Bytes is a thread safe version of bytes.Buffer::Bytes
+func (b *SafeBuffer) Bytes() []byte {
+	b.m.RLock()
+	defer b.m.RUnlock()
+	return b.b.Bytes()
+}
+
+// RequireEventuallyContains is a thread safe eventual checker for the buffer content
+func (b *SafeBuffer) RequireEventuallyContains(t testing.TB, v string) {
+	t.Helper()
+	var bufContents strings.Builder
+	require.Eventuallyf(t, func() bool {
+		b.m.Lock()
+		defer b.m.Unlock()
+		if _, err := b.b.WriteTo(&bufContents); err != nil {
+			require.FailNowf(t, "Failed to copy from buffer",
+				"Error: %v", err)
+		}
+		return strings.Contains(bufContents.String(), v)
+	}, 2*time.Second, 20*time.Millisecond,
+		"Buffer did not contain %q\n============\n%s\n============",
+		v, &bufContents)
+}