diff --git a/.circleci/config.yml b/.circleci/config.yml index 5b4f77ba0de..e7641b41f55 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,4 +1,4 @@ -version: 2 +version: 2.1 jobs: build: docker: @@ -33,3 +33,48 @@ jobs: - store_test_results: path: /tmp/test-results + + integration: + + parameters: + target: + type: string + description: "The makefile target that will run the tests for the integration." + + machine: + image: ubuntu-1604:202004-01 + + environment: + TEST_RESULTS: /tmp/test-results # path to where test results will be saved + INTEGRATION: << parameters.target >> + + steps: + - checkout + + - run: mkdir -p $TEST_RESULTS + + - run: + name: "Integration test $INTEGRATION" + command: | + make $INTEGRATION + find . -name 'coverage.html' > "${TEST_RESULTS}/coverage.lst" + tar -n -cf - -T "${TEST_RESULTS}/coverage.lst" | tar -C "${TEST_RESULTS}" -xvf - + + - store_artifacts: + path: /tmp/test-results + destination: opentelemetry-go-contrib-test-output + + - store_test_results: + path: /tmp/test-results + +workflows: + version: 2.1 + build_and_test: + jobs: + - build + integration_test: + jobs: + - integration: + matrix: + parameters: + target: [test-gocql, test-mongo-driver] diff --git a/.circleci/should_build.sh b/.circleci/should_build.sh new file mode 100755 index 00000000000..1dadd0df45d --- /dev/null +++ b/.circleci/should_build.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# Copyright The OpenTelemetry 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. + +# Returns 0 (true) when the current diff contains files in the provided +# target directory. TARGET should be a unique package name in the directory +# structure. For example, for the gocql integration, set TARGET=gocql so that +# a diff in any of the files in the instrumentation/gocql/gocql directory +# will be picked up by the grep. Diffs are compared against the master branch. + +TARGET=$1 + +if [ -z "$TARGET" ]; then + echo "TARGET is undefined" + exit 1 +fi + +if git diff --name-only origin/master HEAD | grep -q "$TARGET"; then + exit 0 +else + echo "no changes found for $TARGET. skipping tests..." + exit 1 +fi + + + diff --git a/.circleci/wait.sh b/.circleci/wait.sh new file mode 100755 index 00000000000..aa586b3f769 --- /dev/null +++ b/.circleci/wait.sh @@ -0,0 +1,56 @@ +#!/bin/bash + +# Copyright The OpenTelemetry 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. + +wait_for_cassandra () { + for ((i = 0; i < 5; ++i)); do + if docker exec "$1" nodetool status | grep "^UN"; then + exit 0 + fi + echo "Cassandra not yet available" + sleep 10 + done + echo "Timeout waiting for cassandra to initialize" + exit 1 +} + +wait_for_mongo () { + for ((i = 0; i < 5; ++i)); do + if docker exec "$1" mongo; then + exit 0 + fi + echo "Mongo not yet available..." + sleep 10 + done + echo "Timeout waiting for mongo to initialize" + exit 1 +} + +if [ -z "$CMD" ]; then + echo "CMD is undefined. exiting..." + exit 1 +elif [ -z "$IMG_NAME" ]; then + echo "IMG_NAME is undefined. exiting..." + exit 1 +fi + +if [ "$CMD" == "cassandra" ]; then + wait_for_cassandra "$IMG_NAME" +elif [ "$CMD" == "mongo" ]; then + wait_for_mongo "$IMG_NAME" +else + echo "unknown CMD" + exit 1 +fi diff --git a/Makefile b/Makefile index 3c130add118..34d34c565cf 100644 --- a/Makefile +++ b/Makefile @@ -54,6 +54,30 @@ test-with-coverage: .PHONY: ci ci: precommit check-clean-work-tree test-with-coverage test-386 +.PHONY: test-gocql +test-gocql: + @if ./.circleci/should_build.sh gocql; then \ + set -e; \ + docker run --name cass-integ --rm -p 9042:9042 -d cassandra:3; \ + CMD=cassandra IMG_NAME=cass-integ ./.circleci/wait.sh; \ + (cd instrumentation/github.com/gocql/gocql && \ + $(GOTEST_WITH_COVERAGE) . && \ + go tool cover -html=coverage.txt -o coverage.html); \ + docker stop cass-integ; \ + fi + +.PHONY: test-mongo-driver +test-mongo-driver: + @if ./.circleci/should_build.sh mongo-driver; then \ + set -e; \ + docker run --name mongo-integ --rm -p 27017:27017 -d mongo; \ + CMD=mongo IMG_NAME=mongo-integ ./.circleci/wait.sh; \ + (cd instrumentation/go.mongodb.org/mongo-driver && \ + $(GOTEST_WITH_COVERAGE) . && \ + go tool cover -html=coverage.txt -o coverage.html); \ + docker stop mongo-integ; \ + fi + .PHONY: check-clean-work-tree check-clean-work-tree: @if ! git diff --quiet; then \ diff --git a/instrumentation/github.com/gocql/gocql/gocql_test.go b/instrumentation/github.com/gocql/gocql/gocql_test.go index 5e8d15771db..6a069e89179 100644 --- a/instrumentation/github.com/gocql/gocql/gocql_test.go +++ b/instrumentation/github.com/gocql/gocql/gocql_test.go @@ -35,6 +35,8 @@ import ( "github.com/stretchr/testify/assert" mocktracer "go.opentelemetry.io/contrib/internal/trace" + "go.opentelemetry.io/contrib/internal/util" + "go.opentelemetry.io/otel/api/kv" "go.opentelemetry.io/otel/api/metric" export "go.opentelemetry.io/otel/sdk/export/metric" @@ -519,10 +521,7 @@ func afterEach() { } func TestMain(m *testing.M) { - if _, present := os.LookupEnv("INTEGRATION"); !present { - fmt.Println("--- SKIP: to enable integration test, set the INTEGRATION environment variable") - os.Exit(0) - } + util.IntegrationShouldRun("test-gocql") beforeAll() os.Exit(m.Run()) } diff --git a/instrumentation/go.mongodb.org/mongo-driver/mongo_test.go b/instrumentation/go.mongodb.org/mongo-driver/mongo_test.go index f9850022ef6..2e29ccdc32e 100644 --- a/instrumentation/go.mongodb.org/mongo-driver/mongo_test.go +++ b/instrumentation/go.mongodb.org/mongo-driver/mongo_test.go @@ -16,12 +16,12 @@ package mongo import ( "context" - "fmt" "os" "testing" "time" mocktracer "go.opentelemetry.io/contrib/internal/trace" + "go.opentelemetry.io/contrib/internal/util" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" @@ -31,11 +31,7 @@ import ( ) func TestMain(m *testing.M) { - _, ok := os.LookupEnv("INTEGRATION") - if !ok { - fmt.Println("--- SKIP: to enable integration test, set the INTEGRATION environment variable") - os.Exit(0) - } + util.IntegrationShouldRun("test-mongo-driver") os.Exit(m.Run()) } diff --git a/internal/util/testutil.go b/internal/util/testutil.go new file mode 100644 index 00000000000..2754f5cb9a1 --- /dev/null +++ b/internal/util/testutil.go @@ -0,0 +1,31 @@ +// Copyright The OpenTelemetry 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 util + +import ( + "fmt" + "os" +) + +func IntegrationShouldRun(name string) { + if val, ok := os.LookupEnv("INTEGRATION"); !ok || val != name { + fmt.Println( + "--- SKIP: to enable integration test, set the INTEGRATION environment variable", + "to", + fmt.Sprintf("\"%s\"", name), + ) + os.Exit(0) + } +}