diff --git a/magefile.go b/magefile.go index 5c391996b8a..e6ede56d731 100644 --- a/magefile.go +++ b/magefile.go @@ -20,6 +20,7 @@ package main import ( + "context" "fmt" "path/filepath" "time" @@ -105,6 +106,18 @@ func Fields() error { return mage.GenerateFieldsYAML("model") } +// Use RACE_DETECTOR=true to enable the race detector. +func GoTestUnit(ctx context.Context) error { + return mage.GoTest(ctx, mage.DefaultGoTestUnitArgs()) +} + +// GoTestIntegration executes the Go integration tests. +// Use TEST_COVERAGE=true to enable code coverage profiling. +// Use RACE_DETECTOR=true to enable the race detector. +func GoTestIntegration(ctx context.Context) error { + return mage.GoTest(ctx, mage.DefaultGoTestIntegrationArgs()) +} + // ----------------------------------------------------------------------------- // Customizations specific to apm-server. diff --git a/script/jenkins/ci.ps1 b/script/jenkins/ci.ps1 index aa7632952a9..525f143180f 100755 --- a/script/jenkins/ci.ps1 +++ b/script/jenkins/ci.ps1 @@ -1,48 +1,61 @@ -function Exec -{ +function Exec { + [CmdletBinding()] param( - [Parameter(Position=0,Mandatory=1)][scriptblock]$cmd, - [Parameter(Position=1,Mandatory=0)][string]$errorMessage = ($msgs.error_bad_command -f $cmd) + [Parameter(Mandatory = $true)] + [scriptblock]$cmd, + [string]$errorMessage = ($msgs.error_bad_command -f $cmd) ) - & $cmd - if ($LastExitCode -ne 0) { - Write-Error $errorMessage - exit $LastExitCode + try { + $global:lastexitcode = 0 + & $cmd + if ($lastexitcode -ne 0) { + throw $errorMessage + } + } + catch [Exception] { + throw $_ } } # Setup Go. $env:GOPATH = $env:WORKSPACE $env:PATH = "$env:GOPATH\bin;C:\tools\mingw64\bin;$env:PATH" -if (Test-Path -PathType leaf _beats\.go-version) { - & gvm --format=powershell $(Get-Content _beats\.go-version) | Invoke-Expression -} else { - & gvm --format=powershell 1.10.3 | Invoke-Expression -} +& gvm --format=powershell $(Get-Content .go-version) | Invoke-Expression + +# Write cached magefile binaries to workspace to ensure +# each run starts from a clean slate. +$env:MAGEFILE_CACHE = "$env:WORKSPACE\.magefile" + +# Configure testing parameters. +$env:TEST_COVERAGE = "true" +$env:RACE_DETECTOR = "true" + +# Install mage from vendor. +exec { go install github.com/elastic/apm-server/vendor/github.com/magefile/mage } + +echo "Fetching testing dependencies" +# TODO (elastic/beats#5050): Use a vendored copy of this. +exec { go get github.com/docker/libcompose } if (Test-Path "build") { Remove-Item -Recurse -Force build } New-Item -ItemType directory -Path build\coverage | Out-Null New-Item -ItemType directory -Path build\system-tests | Out-Null New-Item -ItemType directory -Path build\system-tests\run | Out-Null -exec { go get -u github.com/jstemmer/go-junit-report } +echo "Building fields.yml" +exec { mage fields } echo "Building $env:beat" -exec { go build } "Build FAILURE" - - -cp .\_meta\fields.common.yml .\_meta\fields.generated.yml -cat model\*\_meta\fields.yml | Out-File -append -encoding UTF8 -filepath .\_meta\fields.generated.yml -cp .\_meta\fields.generated.yml .\fields.yml - - +exec { mage build } "Build FAILURE" echo "Unit testing $env:beat" -go test -v $(go list ./... | select-string -Pattern "vendor" -NotMatch) 2>&1 | Out-File -encoding UTF8 build/TEST-go-unit.out -exec { Get-Content build/TEST-go-unit.out | go-junit-report.exe -set-exit-code | Out-File -encoding UTF8 build/TEST-go-unit.xml } "Unit test FAILURE" +exec { mage goTestUnit } echo "System testing $env:beat" -exec { go test -race -c -cover -covermode=atomic -coverpkg ./... } -exec { cd tests/system } +# Get a CSV list of package names. +$packages = $(go list ./... | select-string -Pattern "/vendor/" -NotMatch | select-string -Pattern "/scripts/cmd/" -NotMatch) +$packages = ($packages|group|Select -ExpandProperty Name) -join "," +exec { go test -race -c -cover -covermode=atomic -coverpkg $packages } "go test FAILURE" +Set-Location -Path tests/system exec { nosetests --with-timer --with-xunit --xunit-file=../../build/TEST-system.xml } "System test FAILURE" diff --git a/tests/system/apmserver.py b/tests/system/apmserver.py index 3ca951bb031..a1bdb9f93bf 100644 --- a/tests/system/apmserver.py +++ b/tests/system/apmserver.py @@ -261,8 +261,7 @@ def check_for_no_smap(self, doc): assert "sourcemap" not in frame -class ClientSideBaseTest(ElasticTest): - +class ClientSideBaseTest(ServerBaseTest): transactions_url = 'http://localhost:8200/v1/rum/transactions' errors_url = 'http://localhost:8200/v1/rum/errors' sourcemap_url = 'http://localhost:8200/v1/rum/sourcemaps' @@ -303,6 +302,8 @@ def upload_sourcemap(self, file_name='bundle_no_mapping.js.map', }) return r + +class ClientSideElasticTest(ClientSideBaseTest, ElasticTest): def wait_for_sourcemaps(self, expected_ct=1): idx = self.smap_index_pattern self.wait_until( @@ -332,7 +333,8 @@ def check_rum_transaction_sourcemap(self, updated, expected_err=None, count=1): span = doc["_source"]["span"] self.check_smap(span, updated, expected_err) - def check_smap(self, doc, updated, err=None): + @staticmethod + def check_smap(doc, updated, err=None): if "stacktrace" not in doc: return for frame in doc["stacktrace"]: @@ -369,14 +371,14 @@ def config(self): return cfg -class SmapCacheBaseTest(ClientSideBaseTest): +class SmapCacheBaseTest(ClientSideElasticTest): def config(self): cfg = super(SmapCacheBaseTest, self).config() cfg.update({"smap_cache_expiration": "1"}) return cfg -class SmapIndexBaseTest(ClientSideBaseTest): +class SmapIndexBaseTest(ClientSideElasticTest): @classmethod def setUpClass(cls): super(SmapIndexBaseTest, cls).setUpClass() diff --git a/tests/system/test_integration.py b/tests/system/test_integration.py index a1efadc4e7d..ce9f8df07e5 100644 --- a/tests/system/test_integration.py +++ b/tests/system/test_integration.py @@ -2,7 +2,7 @@ import unittest from apmserver import ElasticTest, ExpvarBaseTest -from apmserver import ClientSideBaseTest, SmapIndexBaseTest, SmapCacheBaseTest +from apmserver import ClientSideElasticTest, SmapIndexBaseTest, SmapCacheBaseTest from apmserver import SplitIndicesTest from beat.beat import INTEGRATION_TESTS import json @@ -114,7 +114,7 @@ def dump(self, data): return json.dumps(data, indent=4, separators=(',', ': ')) -class RumEnabledIntegrationTest(ClientSideBaseTest): +class RumEnabledIntegrationTest(ClientSideElasticTest): @unittest.skipUnless(INTEGRATION_TESTS, "integration test") def test_backend_error(self): self.load_docs_with_template(self.get_error_payload_path(name="payload.json"), @@ -258,7 +258,7 @@ def test_split_docs_into_separate_indices(self): assert 5 == ct -class SourcemappingIntegrationTest(ClientSideBaseTest): +class SourcemappingIntegrationTest(ClientSideElasticTest): @unittest.skipUnless(INTEGRATION_TESTS, "integration test") def test_backend_error(self):