Merge pull request #9823 from ulyssessouza/add-codecov

Add Codecov
This commit is contained in:
Ulysses Souza 2022-10-17 15:56:59 +02:00 committed by GitHub
commit a6dd996988
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 117 additions and 99 deletions

View File

@ -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
.gitignore vendored
View File

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

View File

@ -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

View File

@ -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")

View File

@ -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)
}

View File

@ -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
}

View File

@ -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}
upOut := &utils.SafeBuffer{}
testCmd := c.NewDockerComposeCmd(t,
"-f=./fixtures/ups-deps-stop/compose.yaml",
"up",
"app",
)
assert.NoError(t, cmd.Start(), "Failed to run compose up")
upCmd = cmd
}()
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
pkg/utils/safebuffer.go Normal file
View File

@ -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)
}