Skip to content

Commit

Permalink
[NH-50167] Run tests on Windows in GHA (#121)
Browse files Browse the repository at this point in the history
  • Loading branch information
swi-jared authored Aug 1, 2024
1 parent 9efdc43 commit e25d4e0
Show file tree
Hide file tree
Showing 14 changed files with 129 additions and 27 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ jobs:
- uses: actions/checkout@v3
- uses: Jerome1337/[email protected]
tests:
runs-on: ubuntu-latest
strategy:
matrix:
goversion: ['1.21', '1.22']
name: Go ${{ matrix.goversion }} tests
os: ['ubuntu-latest', 'windows-latest']
name: Go ${{ matrix.goversion }} (${{ matrix.os}}) tests
runs-on: ${{ matrix.os }}
env:
SW_APM_DEBUG_LEVEL: 1
steps:
Expand Down
35 changes: 27 additions & 8 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"io"
"os"
"path/filepath"
"runtime"
"strings"
"testing"

Expand Down Expand Up @@ -342,14 +343,20 @@ func TestYamlConfig(t *testing.T) {
}

out, err := yaml.Marshal(&yamlConfig)
assert.Nil(t, err)
require.NoError(t, err)

err = os.WriteFile("/tmp/solarwinds-apm-config.yaml", out, 0644)
assert.Nil(t, err)
f, err := os.CreateTemp("", "*-test-config.yaml")
require.NoError(t, err)
defer func() {
_ = f.Close()
os.Remove(f.Name())
}()
err = os.WriteFile(f.Name(), out, 0644)
require.NoError(t, err)

// Test with config file
ClearEnvs()
os.Setenv(envSolarWindsAPMConfigFile, "/tmp/solarwinds-apm-config.yaml")
os.Setenv(envSolarWindsAPMConfigFile, f.Name())

c := NewConfig()
assert.Equal(t, &yamlConfig, c)
Expand Down Expand Up @@ -377,7 +384,7 @@ func TestYamlConfig(t *testing.T) {
}
ClearEnvs()
SetEnvs(envs)
os.Setenv("SW_APM_CONFIG_FILE", "/tmp/solarwinds-apm-config.yaml")
os.Setenv("SW_APM_CONFIG_FILE", f.Name())

envConfig := Config{
Collector: "collector.test.com",
Expand Down Expand Up @@ -458,11 +465,17 @@ func TestInvalidConfigFile(t *testing.T) {
log.SetOutput(os.Stderr)
log.SetLevel(oldLevel)
}()
f, err := os.CreateTemp("", "*-test-config.json")
require.NoError(t, err)
defer func() {
_ = f.Close()
os.Remove(f.Name())
}()

ClearEnvs()
os.Setenv("SW_APM_SERVICE_KEY", "ae38315f6116585d64d82ec2455aa3ec61e02fee25d286f74ace9e4fea189217:go")
os.Setenv("SW_APM_CONFIG_FILE", "/tmp/solarwinds-apm-config.json")
require.NoError(t, os.WriteFile("/tmp/solarwinds-apm-config.json", []byte("hello"), 0644))
os.Setenv("SW_APM_CONFIG_FILE", f.Name())
require.NoError(t, os.WriteFile(f.Name(), []byte("hello"), 0644))

_ = NewConfig()
assert.Contains(t, buf.String(), ErrUnsupportedFormat.Error())
Expand All @@ -474,7 +487,13 @@ func TestInvalidConfigFile(t *testing.T) {
os.Setenv("SW_APM_SERVICE_KEY", "ae38315f6116585d64d82ec2455aa3ec61e02fee25d286f74ace9e4fea189217:go")
os.Setenv("SW_APM_CONFIG_FILE", "/tmp/file-not-exist.yaml")
_ = NewConfig()
assert.Contains(t, buf.String(), "no such file or directory")
var exp string
if runtime.GOOS == "windows" {
exp = "The system cannot find the path specified."
} else {
exp = "no such file or directory"
}
assert.Contains(t, buf.String(), exp)
}

func TestInvalidConfig(t *testing.T) {
Expand Down
9 changes: 5 additions & 4 deletions internal/host/azure/azure_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package azure

import (
"errors"
"github.com/solarwinds/apm-go/internal/testutils"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand All @@ -40,10 +41,10 @@ func TestQueryAzureInvalidJson(t *testing.T) {

func TestQueryAzureNoHttpResponse(t *testing.T) {
m, err := queryAzureIMDS("http://127.0.0.1:12345/asdf")
assert.Error(t, err)
assert.Nil(t, m)
assert.Equal(t, `Get "http://127.0.0.1:12345/asdf?api-version=2021-12-13&format=json": dial tcp 127.0.0.1:12345: connect: connection refused`, err.Error())
assert.Nil(t, m.ToPB())
require.Error(t, err)
require.Nil(t, m)
require.True(t, errors.Is(err, testutils.ConnectionRefusedError), "%+v", err)
require.Nil(t, m.ToPB())
}

func TestQueryAzureIMDS(t *testing.T) {
Expand Down
5 changes: 5 additions & 0 deletions internal/host/k8s/k8s.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,11 @@ func getPodUidFromProc(fn string) (string, error) {
if err != nil {
return "", err
}
defer func() {
if err := f.Close(); err != nil {
log.Warningf("Could not close file: %s", err)
}
}()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Text()
Expand Down
7 changes: 3 additions & 4 deletions internal/host/k8s/k8s_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ func TestRequestMetadataFromEnv(t *testing.T) {
md, err := requestMetadata()
require.Error(t, err)
require.Nil(t, md)
require.Equal(t, "open /run/secrets/kubernetes.io/serviceaccount/namespace: no such file or directory", err.Error())
require.True(t, os.IsNotExist(err))

defer testutils.Setenv(t, "SW_K8S_POD_NAMESPACE", "my env namespace")()
md, err = requestMetadata()
Expand Down Expand Up @@ -124,7 +124,7 @@ func TestRequestMetadataNoNamespace(t *testing.T) {
md, err := requestMetadata()
require.Error(t, err)
require.Nil(t, md)
require.Equal(t, fmt.Sprintf("open %s: no such file or directory", determineNamspaceFileForOS()), err.Error())
require.True(t, os.IsNotExist(err))
}

func TestMetadata_ToPB(t *testing.T) {
Expand Down Expand Up @@ -159,9 +159,8 @@ func TestGetNamespaceNoneFound(t *testing.T) {
require.NoError(t, os.Unsetenv("SW_K8S_POD_NAMESPACE"))
ns, err := getNamespaceFromFile("this file does not exist and should not be opened")
require.Error(t, err)
require.Equal(t, "open this file does not exist and should not be opened: no such file or directory", err.Error())
require.True(t, os.IsNotExist(err))
require.Equal(t, "", ns)

}

// Test getPodName
Expand Down
2 changes: 2 additions & 0 deletions internal/oboe/settings_lambda_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

//go:build !windows

package oboe

import (
Expand Down
19 changes: 12 additions & 7 deletions internal/reporter/certgen.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.

CONFIG=$(mktemp)
echo "[req]
distinguished_name=req_distinguished_name
prompt=no
[san]
subjectAltName=DNS:localhost
[req_distinguished_name]
CN=localhost
" > $CONFIG
echo $CONFIG
openssl req -x509 -newkey rsa:4096 -sha256 -days 365 -nodes \
-keyout for_test.key -out for_test.crt -extensions san -config \
<(echo "[req]";
echo distinguished_name=req;
echo "[san]";
echo subjectAltName=DNS:localhost
) \
-subj "/CN=localhost"
-keyout for_test.key -out for_test.crt -extensions san -config "$CONFIG"
rm $CONFIG
13 changes: 13 additions & 0 deletions internal/reporter/reporter_grpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// There's an issue in GitHub Actions running Windows that causes `net.Listen`
// to fail with:
//
// listen tcp: lookup localhost: getaddrinfow: A non-recoverable error
// occurred during a database lookup.
//
// For now, we're going to rely on non-windows to verify that this code works.
// Over time, the (non-OTLP) grpc implementation will be phased out, so I think
// this is a reasonable compromise.
// -- @swi-jared

//go:build !windows

package reporter

import (
Expand Down
3 changes: 3 additions & 0 deletions internal/reporter/reporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// See note in `reporter_grpc_test.go`
//go:build !windows

package reporter

import (
Expand Down
21 changes: 21 additions & 0 deletions internal/testutils/testutils_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// © 2023 SolarWinds Worldwide, LLC. All rights reserved.
//
// 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.

//go:build !windows

package testutils

import "syscall"

const ConnectionRefusedError = syscall.ECONNREFUSED
21 changes: 21 additions & 0 deletions internal/testutils/testutils_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// © 2023 SolarWinds Worldwide, LLC. All rights reserved.
//
// 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.

//go:build windows

package testutils

import "golang.org/x/sys/windows"

const ConnectionRefusedError = windows.WSAECONNREFUSED
4 changes: 3 additions & 1 deletion internal/uams/file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
package uams

import (
"errors"
"fmt"
"github.com/google/uuid"
"github.com/stretchr/testify/require"
"io/fs"
"os"
"testing"
)
Expand All @@ -29,7 +31,7 @@ func TestReadFromFileNoExists(t *testing.T) {
uid, err := ReadFromFile(testfile)
require.Equal(t, uuid.Nil, uid)
require.Error(t, err)
require.Equal(t, "could not stat uams client file: stat /tmp/foobarbaz: no such file or directory", err.Error())
require.True(t, errors.Is(err, fs.ErrNotExist))
}

func TestReadFromFileDirectory(t *testing.T) {
Expand Down
3 changes: 2 additions & 1 deletion internal/uams/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package uams

import (
"errors"
"fmt"
"github.com/google/uuid"
"github.com/solarwinds/apm-go/internal/testutils"
Expand All @@ -27,7 +28,7 @@ func TestReadFromHttpConnRefused(t *testing.T) {
uid, err := ReadFromHttp("http://127.0.0.1:12345")
require.Error(t, err)
require.Equal(t, uuid.Nil, uid)
require.Equal(t, `Get "http://127.0.0.1:12345": dial tcp 127.0.0.1:12345: connect: connection refused`, err.Error())
require.True(t, errors.Is(err, testutils.ConnectionRefusedError), "%+v", err)
}

func TestReadFromHttp(t *testing.T) {
Expand Down
9 changes: 9 additions & 0 deletions internal/uams/uams_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"net/http"
"os"
"path/filepath"
"runtime"
"testing"
"time"
)
Expand All @@ -38,7 +39,15 @@ func TestUpdateClientId(t *testing.T) {
uid, err := uuid.NewRandom()
require.NoError(t, err)
a := time.Now()
// windows doesn't seem to notice that a few nanoseconds have passed, so we
// introduce a touch of delay
if runtime.GOOS == "windows" {
time.Sleep(time.Millisecond)
}
updateClientId(uid, "file")
if runtime.GOOS == "windows" {
time.Sleep(time.Millisecond)
}
b := time.Now()
require.Equal(t, uid, currState.clientId)
require.Equal(t, "file", currState.via)
Expand Down

0 comments on commit e25d4e0

Please sign in to comment.