GODT-1364: Add windows CI machine for tests, and build
This commit is contained in:
@ -48,7 +48,7 @@ lint:
|
|||||||
tags:
|
tags:
|
||||||
- medium
|
- medium
|
||||||
|
|
||||||
test:
|
test-linux:
|
||||||
stage: test
|
stage: test
|
||||||
only:
|
only:
|
||||||
- branches
|
- branches
|
||||||
@ -65,6 +65,14 @@ test:
|
|||||||
tags:
|
tags:
|
||||||
- medium
|
- medium
|
||||||
|
|
||||||
|
test-windows:
|
||||||
|
extends: .build-windows-base
|
||||||
|
stage: test
|
||||||
|
only:
|
||||||
|
- branches
|
||||||
|
script:
|
||||||
|
- make test
|
||||||
|
|
||||||
test-integration:
|
test-integration:
|
||||||
stage: test
|
stage: test
|
||||||
only:
|
only:
|
||||||
@ -96,6 +104,7 @@ build-qml:
|
|||||||
- cd internal/frontend/qml
|
- cd internal/frontend/qml
|
||||||
- tar -cvzf ../../../bridge_qml.tgz ./*
|
- tar -cvzf ../../../bridge_qml.tgz ./*
|
||||||
|
|
||||||
|
|
||||||
.build-base:
|
.build-base:
|
||||||
stage: build
|
stage: build
|
||||||
only:
|
only:
|
||||||
@ -134,6 +143,7 @@ build-linux-qa:
|
|||||||
paths:
|
paths:
|
||||||
- bridge_*.tgz
|
- bridge_*.tgz
|
||||||
|
|
||||||
|
|
||||||
.build-darwin-base:
|
.build-darwin-base:
|
||||||
extends: .build-base
|
extends: .build-base
|
||||||
before_script:
|
before_script:
|
||||||
@ -170,6 +180,40 @@ build-darwin-qa:
|
|||||||
paths:
|
paths:
|
||||||
- bridge_*.tgz
|
- bridge_*.tgz
|
||||||
|
|
||||||
|
|
||||||
|
.build-windows-base:
|
||||||
|
extends: .build-base
|
||||||
|
before_script:
|
||||||
|
- export GOROOT=/c/Go
|
||||||
|
- export PATH=$GOROOT/bin:$PATH
|
||||||
|
- export GOARCH=amd64
|
||||||
|
- export GOPATH=~/go
|
||||||
|
- export GO111MODULE=on
|
||||||
|
- export PATH=$GOPATH/bin:$PATH
|
||||||
|
- export MSYSTEM=
|
||||||
|
- export PATH=$PATH:/c/grrrQt/5.13.2/mingw73_64/bin
|
||||||
|
tags:
|
||||||
|
- windows-bridge
|
||||||
|
|
||||||
|
build-windows:
|
||||||
|
extends: .build-windows-base
|
||||||
|
artifacts:
|
||||||
|
name: "bridge-windows-$CI_COMMIT_SHORT_SHA"
|
||||||
|
paths:
|
||||||
|
- bridge_*.tgz
|
||||||
|
|
||||||
|
build-windows-qa:
|
||||||
|
extends: .build-windows-base
|
||||||
|
only:
|
||||||
|
- web
|
||||||
|
- branches
|
||||||
|
script:
|
||||||
|
- BUILD_TAGS="build_qa" make build
|
||||||
|
artifacts:
|
||||||
|
name: "bridge-windows-qa-$CI_COMMIT_SHORT_SHA"
|
||||||
|
paths:
|
||||||
|
- bridge_*.tgz
|
||||||
|
|
||||||
# Stage: MIRROR
|
# Stage: MIRROR
|
||||||
|
|
||||||
mirror-repo:
|
mirror-repo:
|
||||||
|
|||||||
@ -25,81 +25,118 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
const testPrefFilePath = "/tmp/pref.json"
|
|
||||||
|
|
||||||
func TestLoadNoKeyValueStore(t *testing.T) {
|
func TestLoadNoKeyValueStore(t *testing.T) {
|
||||||
pref := newTestEmptyKeyValueStore(t)
|
r := require.New(t)
|
||||||
require.Equal(t, "", pref.Get("key"))
|
pref, clean := newTestEmptyKeyValueStore(r)
|
||||||
|
defer clean()
|
||||||
|
|
||||||
|
r.Equal("", pref.Get("key"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLoadBadKeyValueStore(t *testing.T) {
|
func TestLoadBadKeyValueStore(t *testing.T) {
|
||||||
require.NoError(t, ioutil.WriteFile(testPrefFilePath, []byte("{\"key\":\"value"), 0700))
|
r := require.New(t)
|
||||||
pref := newKeyValueStore(testPrefFilePath)
|
path, clean := newTmpFile(r)
|
||||||
require.Equal(t, "", pref.Get("key"))
|
defer clean()
|
||||||
|
|
||||||
|
r.NoError(ioutil.WriteFile(path, []byte("{\"key\":\"MISSING_QUOTES"), 0700))
|
||||||
|
pref := newKeyValueStore(path)
|
||||||
|
r.Equal("", pref.Get("key"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestKeyValueStoreGet(t *testing.T) {
|
func TestKeyValueStor(t *testing.T) {
|
||||||
pref := newTestKeyValueStore(t)
|
r := require.New(t)
|
||||||
require.Equal(t, "value", pref.Get("str"))
|
pref, clean := newTestKeyValueStore(r)
|
||||||
require.Equal(t, "42", pref.Get("int"))
|
defer clean()
|
||||||
require.Equal(t, "true", pref.Get("bool"))
|
|
||||||
require.Equal(t, "t", pref.Get("falseBool"))
|
r.Equal("value", pref.Get("str"))
|
||||||
|
r.Equal("42", pref.Get("int"))
|
||||||
|
r.Equal("true", pref.Get("bool"))
|
||||||
|
r.Equal("t", pref.Get("falseBool"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestKeyValueStoreGetInt(t *testing.T) {
|
func TestKeyValueStoreGetInt(t *testing.T) {
|
||||||
pref := newTestKeyValueStore(t)
|
r := require.New(t)
|
||||||
require.Equal(t, 0, pref.GetInt("str"))
|
pref, clean := newTestKeyValueStore(r)
|
||||||
require.Equal(t, 42, pref.GetInt("int"))
|
defer clean()
|
||||||
require.Equal(t, 0, pref.GetInt("bool"))
|
|
||||||
require.Equal(t, 0, pref.GetInt("falseBool"))
|
r.Equal(0, pref.GetInt("str"))
|
||||||
|
r.Equal(42, pref.GetInt("int"))
|
||||||
|
r.Equal(0, pref.GetInt("bool"))
|
||||||
|
r.Equal(0, pref.GetInt("falseBool"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestKeyValueStoreGetBool(t *testing.T) {
|
func TestKeyValueStoreGetBool(t *testing.T) {
|
||||||
pref := newTestKeyValueStore(t)
|
r := require.New(t)
|
||||||
require.Equal(t, false, pref.GetBool("str"))
|
pref, clean := newTestKeyValueStore(r)
|
||||||
require.Equal(t, false, pref.GetBool("int"))
|
defer clean()
|
||||||
require.Equal(t, true, pref.GetBool("bool"))
|
|
||||||
require.Equal(t, false, pref.GetBool("falseBool"))
|
r.Equal(false, pref.GetBool("str"))
|
||||||
|
r.Equal(false, pref.GetBool("int"))
|
||||||
|
r.Equal(true, pref.GetBool("bool"))
|
||||||
|
r.Equal(false, pref.GetBool("falseBool"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestKeyValueStoreSetDefault(t *testing.T) {
|
func TestKeyValueStoreSetDefault(t *testing.T) {
|
||||||
pref := newTestEmptyKeyValueStore(t)
|
r := require.New(t)
|
||||||
|
pref, clean := newTestEmptyKeyValueStore(r)
|
||||||
|
defer clean()
|
||||||
|
|
||||||
pref.setDefault("key", "value")
|
pref.setDefault("key", "value")
|
||||||
pref.setDefault("key", "othervalue")
|
pref.setDefault("key", "othervalue")
|
||||||
require.Equal(t, "value", pref.Get("key"))
|
r.Equal("value", pref.Get("key"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestKeyValueStoreSet(t *testing.T) {
|
func TestKeyValueStoreSet(t *testing.T) {
|
||||||
pref := newTestEmptyKeyValueStore(t)
|
r := require.New(t)
|
||||||
|
pref, clean := newTestEmptyKeyValueStore(r)
|
||||||
|
defer clean()
|
||||||
|
|
||||||
pref.Set("str", "value")
|
pref.Set("str", "value")
|
||||||
checkSavedKeyValueStore(t, "{\n\t\"str\": \"value\"\n}")
|
checkSavedKeyValueStore(r, pref.path, "{\n\t\"str\": \"value\"\n}")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestKeyValueStoreSetInt(t *testing.T) {
|
func TestKeyValueStoreSetInt(t *testing.T) {
|
||||||
pref := newTestEmptyKeyValueStore(t)
|
r := require.New(t)
|
||||||
|
pref, clean := newTestEmptyKeyValueStore(r)
|
||||||
|
defer clean()
|
||||||
|
|
||||||
pref.SetInt("int", 42)
|
pref.SetInt("int", 42)
|
||||||
checkSavedKeyValueStore(t, "{\n\t\"int\": \"42\"\n}")
|
checkSavedKeyValueStore(r, pref.path, "{\n\t\"int\": \"42\"\n}")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestKeyValueStoreSetBool(t *testing.T) {
|
func TestKeyValueStoreSetBool(t *testing.T) {
|
||||||
pref := newTestEmptyKeyValueStore(t)
|
r := require.New(t)
|
||||||
|
pref, clean := newTestEmptyKeyValueStore(r)
|
||||||
|
defer clean()
|
||||||
|
|
||||||
pref.SetBool("trueBool", true)
|
pref.SetBool("trueBool", true)
|
||||||
pref.SetBool("falseBool", false)
|
pref.SetBool("falseBool", false)
|
||||||
checkSavedKeyValueStore(t, "{\n\t\"falseBool\": \"false\",\n\t\"trueBool\": \"true\"\n}")
|
checkSavedKeyValueStore(r, pref.path, "{\n\t\"falseBool\": \"false\",\n\t\"trueBool\": \"true\"\n}")
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTestEmptyKeyValueStore(t *testing.T) *keyValueStore {
|
func newTmpFile(r *require.Assertions) (path string, clean func()) {
|
||||||
require.NoError(t, os.RemoveAll(testPrefFilePath))
|
tmpfile, err := ioutil.TempFile("", "pref.*.json")
|
||||||
return newKeyValueStore(testPrefFilePath)
|
r.NoError(err)
|
||||||
|
defer r.NoError(tmpfile.Close())
|
||||||
|
|
||||||
|
return tmpfile.Name(), func() {
|
||||||
|
r.NoError(os.Remove(tmpfile.Name()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTestKeyValueStore(t *testing.T) *keyValueStore {
|
func newTestEmptyKeyValueStore(r *require.Assertions) (*keyValueStore, func()) {
|
||||||
require.NoError(t, ioutil.WriteFile(testPrefFilePath, []byte("{\"str\":\"value\",\"int\":\"42\",\"bool\":\"true\",\"falseBool\":\"t\"}"), 0700))
|
path, clean := newTmpFile(r)
|
||||||
return newKeyValueStore(testPrefFilePath)
|
return newKeyValueStore(path), clean
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkSavedKeyValueStore(t *testing.T, expected string) {
|
func newTestKeyValueStore(r *require.Assertions) (*keyValueStore, func()) {
|
||||||
data, err := ioutil.ReadFile(testPrefFilePath)
|
path, clean := newTmpFile(r)
|
||||||
require.NoError(t, err)
|
r.NoError(ioutil.WriteFile(path, []byte("{\"str\":\"value\",\"int\":\"42\",\"bool\":\"true\",\"falseBool\":\"t\"}"), 0700))
|
||||||
require.Equal(t, expected, string(data))
|
return newKeyValueStore(path), clean
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkSavedKeyValueStore(r *require.Assertions, path, expected string) {
|
||||||
|
data, err := ioutil.ReadFile(path)
|
||||||
|
r.NoError(err)
|
||||||
|
r.Equal(expected, string(data))
|
||||||
}
|
}
|
||||||
|
|||||||
8
internal/store/cache/disk.go
vendored
8
internal/store/cache/disk.go
vendored
@ -63,10 +63,16 @@ func NewOnDiskCache(path string, cmp Compressor, opts Options) (Cache, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
file, err := ioutil.TempFile(path, "tmp")
|
file, err := ioutil.TempFile(path, "tmp")
|
||||||
|
defer func() {
|
||||||
|
file.Close() //nolint[errcheck]
|
||||||
|
os.Remove(file.Name()) //nolint[errcheck]
|
||||||
|
}()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("cannot open test write target: %w", err)
|
||||||
|
}
|
||||||
|
if _, err := file.Write([]byte("test-write")); err != nil {
|
||||||
return nil, fmt.Errorf("cannot write to target: %w", err)
|
return nil, fmt.Errorf("cannot write to target: %w", err)
|
||||||
}
|
}
|
||||||
os.Remove(file.Name()) //nolint[errcheck]
|
|
||||||
|
|
||||||
usage := du.NewDiskUsage(path)
|
usage := du.NewDiskUsage(path)
|
||||||
|
|
||||||
|
|||||||
@ -229,7 +229,10 @@ func (u *Users) MigrateCache(srcPath, dstPath string) error {
|
|||||||
// (read-only is conserved). Do copy instead.
|
// (read-only is conserved). Do copy instead.
|
||||||
tmp, err := ioutil.TempFile(srcPath, "tmp")
|
tmp, err := ioutil.TempFile(srcPath, "tmp")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
defer os.Remove(tmp.Name()) //nolint[errcheck]
|
defer func() {
|
||||||
|
tmp.Close() //nolint[errcheck]
|
||||||
|
os.Remove(tmp.Name()) //nolint[errcheck]
|
||||||
|
}()
|
||||||
|
|
||||||
if err := os.Rename(srcPath, dstPath); err == nil {
|
if err := os.Rename(srcPath, dstPath); err == nil {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -175,6 +175,7 @@ func initMocks(t *testing.T) mocks {
|
|||||||
|
|
||||||
cacheFile, err := ioutil.TempFile("", "bridge-store-cache-*.db")
|
cacheFile, err := ioutil.TempFile("", "bridge-store-cache-*.db")
|
||||||
r.NoError(t, err, "could not get temporary file for store cache")
|
r.NoError(t, err, "could not get temporary file for store cache")
|
||||||
|
r.NoError(t, cacheFile.Close())
|
||||||
|
|
||||||
m := mocks{
|
m := mocks{
|
||||||
t: t,
|
t: t,
|
||||||
@ -201,6 +202,7 @@ func initMocks(t *testing.T) mocks {
|
|||||||
|
|
||||||
dbFile, err := ioutil.TempFile(t.TempDir(), "bridge-store-db-*.db")
|
dbFile, err := ioutil.TempFile(t.TempDir(), "bridge-store-db-*.db")
|
||||||
r.NoError(t, err, "could not get temporary file for store db")
|
r.NoError(t, err, "could not get temporary file for store db")
|
||||||
|
r.NoError(t, dbFile.Close())
|
||||||
|
|
||||||
return store.New(
|
return store.New(
|
||||||
sentryReporter,
|
sentryReporter,
|
||||||
|
|||||||
@ -32,7 +32,7 @@ import (
|
|||||||
// RemoveOldVersions is a noop on darwin; we don't test it there.
|
// RemoveOldVersions is a noop on darwin; we don't test it there.
|
||||||
|
|
||||||
func TestRemoveOldVersions(t *testing.T) {
|
func TestRemoveOldVersions(t *testing.T) {
|
||||||
updates, err := ioutil.TempDir("", "updates")
|
updates, err := ioutil.TempDir(t.TempDir(), "updates")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
v := newTestVersioner(t, "myCoolApp", updates, "2.3.4-beta", "2.3.4", "2.3.5", "2.4.0")
|
v := newTestVersioner(t, "myCoolApp", updates, "2.3.4-beta", "2.3.4", "2.3.5", "2.4.0")
|
||||||
|
|||||||
@ -65,11 +65,13 @@ func makeDummyVersionDirectory(t *testing.T, exeName, updates, version string) s
|
|||||||
exe, err := os.Create(filepath.Join(target, getExeName(exeName)))
|
exe, err := os.Create(filepath.Join(target, getExeName(exeName)))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, exe)
|
require.NotNil(t, exe)
|
||||||
|
require.NoError(t, exe.Close())
|
||||||
require.NoError(t, os.Chmod(exe.Name(), 0700))
|
require.NoError(t, os.Chmod(exe.Name(), 0700))
|
||||||
|
|
||||||
sig, err := os.Create(filepath.Join(target, getExeName(exeName)+".sig"))
|
sig, err := os.Create(filepath.Join(target, getExeName(exeName)+".sig"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, sig)
|
require.NotNil(t, sig)
|
||||||
|
require.NoError(t, sig.Close())
|
||||||
|
|
||||||
return target
|
return target
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,6 +21,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -33,6 +34,7 @@ var (
|
|||||||
wantOutput = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
|
wantOutput = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
|
||||||
testProcessSleep = 100 // ms
|
testProcessSleep = 100 // ms
|
||||||
runParallelTimeOverhead = 150 // ms
|
runParallelTimeOverhead = 150 // ms
|
||||||
|
windowsCIExtra = 250 // ms - estimated experimentally
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParallel(t *testing.T) {
|
func TestParallel(t *testing.T) {
|
||||||
@ -56,6 +58,9 @@ func TestParallel(t *testing.T) {
|
|||||||
|
|
||||||
wantMinDuration := int(math.Ceil(float64(len(testInput))/float64(workers))) * testProcessSleep
|
wantMinDuration := int(math.Ceil(float64(len(testInput))/float64(workers))) * testProcessSleep
|
||||||
wantMaxDuration := wantMinDuration + runParallelTimeOverhead
|
wantMaxDuration := wantMinDuration + runParallelTimeOverhead
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
wantMaxDuration += windowsCIExtra
|
||||||
|
}
|
||||||
r.True(t, duration.Nanoseconds() > int64(wantMinDuration*1000000), "Duration too short: %v (expected: %v)", duration, wantMinDuration)
|
r.True(t, duration.Nanoseconds() > int64(wantMinDuration*1000000), "Duration too short: %v (expected: %v)", duration, wantMinDuration)
|
||||||
r.True(t, duration.Nanoseconds() < int64(wantMaxDuration*1000000), "Duration too long: %v (expected: %v)", duration, wantMaxDuration)
|
r.True(t, duration.Nanoseconds() < int64(wantMaxDuration*1000000), "Duration too long: %v (expected: %v)", duration, wantMaxDuration)
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user