Skip to content

Commit

Permalink
Merge branch 'main' into contrib-tp
Browse files Browse the repository at this point in the history
  • Loading branch information
b1ron authored Aug 21, 2023
2 parents e237279 + 0abee3f commit a245f5f
Show file tree
Hide file tree
Showing 11 changed files with 977 additions and 74 deletions.
7 changes: 2 additions & 5 deletions .github/workflows/dance-trust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,19 +68,16 @@ jobs:
working-directory: tools

- name: Start environment
run: bin/task env-up-detach
run: bin/task env-up-detach DB=${{ matrix.db }}
env:
FERRETDB_IMAGE: ghcr.io/ferretdb/ferretdb-dev:main
DB: ${{ matrix.db }}

- name: Run init
run: bin/task init

- name: Dance!
run: bin/task dance
run: bin/task dance DB=${{ matrix.db }} TEST=${{ matrix.test }} PARALLEL=10
env:
DB: ${{ matrix.db }}
TEST: ${{ matrix.test }}
NMSHD_TEST_BASEURL: ${{ secrets.NMSHD_TEST_BASEURL }}
NMSHD_TEST_CLIENTID: ${{ secrets.NMSHD_TEST_CLIENTID }}
NMSHD_TEST_CLIENTSECRET: ${{ secrets.NMSHD_TEST_CLIENTSECRET }}
Expand Down
10 changes: 3 additions & 7 deletions .github/workflows/dance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
dance:
name: dance
runs-on: ubuntu-22.04
timeout-minutes: 30
timeout-minutes: 120

# Do not run this job in parallel for any PR change or branch push
# to save some resources.
Expand Down Expand Up @@ -72,19 +72,15 @@ jobs:
working-directory: tools

- name: Start environment
run: bin/task env-up-detach
run: bin/task env-up-detach DB=${{ matrix.db }}
env:
FERRETDB_IMAGE: ghcr.io/ferretdb/ferretdb-dev:main
DB: ${{ matrix.db }}

- name: Run init
run: bin/task init

- name: Dance!
run: bin/task dance
env:
DB: ${{ matrix.db }}
TEST: ${{ matrix.test }}
run: bin/task dance DB=${{ matrix.db }} TEST=${{ matrix.test }} PARALLEL=10

- name: Collect logs
if: failure()
Expand Down
5 changes: 4 additions & 1 deletion Taskfile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ version: "3"

vars:
REPLSET: postgres mongodb_replset init_mongodb_replset
DB: ""
TEST: ""
PARALLEL: 0

tasks:
init-tools:
Expand Down Expand Up @@ -75,7 +78,7 @@ tasks:
desc: "Run all integration tests"
dir: tests
cmds:
- go run ../cmd/dance -db={{.DB}} {{.TEST}}
- go run ../cmd/dance -db={{.DB}} -p={{.PARALLEL}} {{.TEST}}
preconditions:
- sh: "test {{.DB}}"
msg: "Please set DB variable to one of `ferretdb`, `mongodb`"
Expand Down
5 changes: 3 additions & 2 deletions cmd/dance/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ func logResult(label string, res map[string]string) {
func main() {
dbF := flag.String("db", "", "database to use: ferretdb, mongodb")
vF := flag.Bool("v", false, "be verbose")
pF := flag.Int("p", 0, "number of tests to run in parallel")
log.SetFlags(0)
flag.Parse()

Expand Down Expand Up @@ -130,9 +131,9 @@ func main() {
case internal.RunnerTypeCommand:
runRes, err = command.Run(ctx, dir, config.Args)
case internal.RunnerTypeGoTest:
runRes, err = gotest.Run(ctx, dir, config.Args, *vF)
runRes, err = gotest.Run(ctx, dir, config.Args, *vF, *pF)
case internal.RunnerTypeJSTest:
runRes, err = jstest.Run(ctx, dir, config.Args)
runRes, err = jstest.Run(ctx, dir, config.Args, *pF)
case internal.RunnerTypeYCSB:
runRes, err = ycsb.Run(ctx, dir, config.Args)
default:
Expand Down
6 changes: 5 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ services:
depends_on: ["postgres"]
ports:
- 27017:27017
command: -test.coverprofile=cover.txt --
environment:
# Always UTC+05:45. Set to catch timezone problems.
- TZ=Asia/Kathmandu
Expand Down Expand Up @@ -39,6 +38,11 @@ services:
command: --setParameter enableTestCommands=1
container_name: dance_mongodb
restart: unless-stopped
ulimits:
nproc: 64000
nofile:
soft: 64000
hard: 64000
ports:
- 27017:27017
environment:
Expand Down
16 changes: 14 additions & 2 deletions internal/gotest/gotest.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,12 @@ import (
"context"
"encoding/json"
"io"
"log"
"os"
"os/exec"
"runtime"
"strconv"
"strings"

"github.com/FerretDB/dance/internal"
)
Expand All @@ -30,11 +33,17 @@ import (
// Args contain additional arguments to `go test`.
// `-v -json -count=1` are always added.
// `-race` is added if possible.
func Run(ctx context.Context, dir string, args []string, verbose bool) (*internal.TestResults, error) {
func Run(ctx context.Context, dir string, args []string, verbose bool, parallel int) (*internal.TestResults, error) {
// TODO https://github.com/FerretDB/dance/issues/20
_ = ctx

args = append([]string{"test", "-v", "-json", "-count=1"}, args...)
args = append([]string{"test", "-v", "-json", "-p=1", "-count=1"}, args...)

// implicitly defaults to GOMAXPROCS
if parallel > 0 {
log.Printf("Running up to %d tests in parallel.", parallel)
args = append(args, "-parallel="+strconv.Itoa(parallel))
}

// use the same condition as in FerretDB's Taskfile.yml
if runtime.GOOS != "windows" && runtime.GOARCH != "arm" && runtime.GOARCH != "riscv64" {
Expand All @@ -44,6 +53,9 @@ func Run(ctx context.Context, dir string, args []string, verbose bool) (*interna
cmd := exec.Command("go", args...)
cmd.Dir = dir
cmd.Stderr = os.Stderr

log.Printf("Running %s", strings.Join(cmd.Args, " "))

p, err := cmd.StdoutPipe()
if err != nil {
return nil, err
Expand Down
70 changes: 35 additions & 35 deletions internal/jstest/jstest.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import (
"log"
"os/exec"
"path/filepath"
"runtime"
"strings"
"sync"

"golang.org/x/exp/maps"

Expand All @@ -33,7 +33,7 @@ import (

// Run runs `mongo`.
// Args is a list of filepath.Glob file patterns with additional support for !exclude.
func Run(ctx context.Context, dir string, args []string) (*internal.TestResults, error) {
func Run(ctx context.Context, dir string, args []string, parallel int) (*internal.TestResults, error) {
// TODO https://github.com/FerretDB/dance/issues/20
_ = ctx

Expand Down Expand Up @@ -73,10 +73,8 @@ func Run(ctx context.Context, dir string, args []string) (*internal.TestResults,

files := maps.Keys(filesM)

log.Printf("Total number of tests to run %d\n", len(files))

res := &internal.TestResults{
TestResults: make(map[string]internal.TestResult),
TestResults: make(map[string]internal.TestResult, len(files)),
}

type item struct {
Expand All @@ -85,41 +83,43 @@ func Run(ctx context.Context, dir string, args []string) (*internal.TestResults,
out []byte
}

// tokens is a counting semaphore used to enforce a limit of 20 concurrent calls to runShellWithScript.
tokens := make(chan struct{}, 20)
input := make(chan string, len(files))
output := make(chan *item, len(files))

ch := make(chan *item, len(files))
if parallel <= 0 {
parallel = runtime.NumCPU()
}

var wg sync.WaitGroup
for _, f := range files {
wg.Add(1)
log.Printf("Running up to %d tests in parallel.", parallel)

go func(f string) {
defer wg.Done()
for i := 0; i < parallel; i++ {
go func() {
for f := range input {
it := &item{
file: f,
}

tokens <- struct{}{}
it := &item{
file: f,
}
// we set working_dir so use a relative path here instead
rel, err := filepath.Rel("mongo", f)
if err != nil {
panic(err)
}

// we set working_dir so use a relative path here instead
rel, err := filepath.Rel("mongo", f)
if err != nil {
panic(err)
it.out, it.err = runMongo(dir, rel)
output <- it
}
}()
}

it.out, it.err = runShellWithScript(dir, rel)
ch <- it

<-tokens // release the token
}(f)
for _, f := range files {
input <- f
}

wg.Wait()
close(input)

close(ch)
for i := 0; i < len(files); i++ {
it := <-output

for it := range ch {
if it.err != nil {
var exitErr *exec.ExitError
if !errors.As(it.err, &exitErr) {
Expand All @@ -142,8 +142,8 @@ func Run(ctx context.Context, dir string, args []string) (*internal.TestResults,
return res, nil
}

// runShellWithScript runs the mongo shell inside a container with script and returns the combined output.
func runShellWithScript(dir, script string) ([]byte, error) {
// runMongo runs the mongo shell inside a container with file and returns the combined output.
func runMongo(dir, file string) ([]byte, error) {
bin, err := exec.LookPath("docker")
if err != nil {
return nil, err
Expand All @@ -152,7 +152,7 @@ func runShellWithScript(dir, script string) ([]byte, error) {
dockerArgs := []string{"compose", "run", "-T", "--rm", "mongo"}
shellArgs := []string{
"--verbose", "--norc", "mongodb://host.docker.internal:27017/",
"--eval", evalBuilder(script), script,
"--eval", evalBuilder(file), file,
}
dockerArgs = append(dockerArgs, shellArgs...)

Expand All @@ -165,11 +165,11 @@ func runShellWithScript(dir, script string) ([]byte, error) {
}

// evalBuilder creates the TestData object and sets the testName property for the shell.
func evalBuilder(script string) string {
func evalBuilder(file string) string {
var eb bytes.Buffer
fmt.Fprintf(&eb, "TestData = new Object(); ")
scriptName := filepath.Base(script)
fmt.Fprintf(&eb, "TestData.testName = %q;", strings.TrimSuffix(scriptName, filepath.Ext(scriptName)))
fileName := filepath.Base(file)
fmt.Fprintf(&eb, "TestData.testName = %q;", strings.TrimSuffix(fileName, filepath.Ext(fileName)))

return eb.String()
}
Loading

0 comments on commit a245f5f

Please sign in to comment.