Skip to content

Commit

Permalink
Merge pull request #2353 from nspcc-dev/fix-win-tests
Browse files Browse the repository at this point in the history
*: fix windows tests
  • Loading branch information
roman-khimov committed Feb 10, 2022
2 parents 32a7e97 + 0760e54 commit acd348c
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 53 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/publish_to_dockerhub.yml
Expand Up @@ -128,9 +128,6 @@ jobs:
run: make test
publish_wsc:
# Ensure test job passes before pushing image.
# TODO: currently test_wsc job is failing, so we have `always()` condition.
# After #2269 and #2268 this condition should be removed.
if: ${{ always() }}
needs: tests_wsc
name: Publish WindowsServerCore-based image to DockerHub
runs-on: windows-2022
Expand All @@ -141,6 +138,9 @@ jobs:
# Allows to fetch all history for all branches and tags. Need this for proper versioning.
fetch-depth: 0

- name: Show docker images
run: docker images

- name: Build image
run: make image-wsc

Expand Down
22 changes: 21 additions & 1 deletion Dockerfile.wsc
@@ -1,5 +1,25 @@
# Builder image
FROM golang:windowsservercore-ltsc2022 as builder
FROM mcr.microsoft.com/windows/servercore:ltsc2022 as builder

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop';", "$ProgressPreference = 'SilentlyContinue';"]

ENV GIT_VERSION=2.23.0

ENV GIT_TAG=v2.23.0.windows.1

ENV GIT_DOWNLOAD_URL=https://github.com/git-for-windows/git/releases/download/v2.23.0.windows.1/MinGit-2.23.0-64-bit.zip

ENV GIT_DOWNLOAD_SHA256=8f65208f92c0b4c3ae4c0cf02d4b5f6791d539cd1a07b2df62b7116467724735

RUN Write-Host ('Downloading {0} ...' -f $env:GIT_DOWNLOAD_URL); [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -Uri $env:GIT_DOWNLOAD_URL -OutFile 'git.zip'; Write-Host ('Verifying sha256 ({0}) ...' -f $env:GIT_DOWNLOAD_SHA256); if ((Get-FileHash git.zip -Algorithm sha256).Hash -ne $env:GIT_DOWNLOAD_SHA256) { Write-Host 'FAILED!'; exit 1; }; Write-Host 'Expanding ...'; Expand-Archive -Path git.zip -DestinationPath C:\git\.; Write-Host 'Removing ...'; Remove-Item git.zip -Force; Write-Host 'Updating PATH ...'; $env:PATH = 'C:\git\cmd;C:\git\mingw64\bin;C:\git\usr\bin;' + $env:PATH; [Environment]::SetEnvironmentVariable('PATH', $env:PATH, [EnvironmentVariableTarget]::Machine); Write-Host 'Verifying install ("git version") ...'; git version; Write-Host 'Complete.';

ENV GOPATH=C:\\go

RUN $newPath = ('{0}\bin;C:\Program Files\Go\bin;{1}' -f $env:GOPATH, $env:PATH); Write-Host ('Updating PATH: {0}' -f $newPath); [Environment]::SetEnvironmentVariable('PATH', $newPath, [EnvironmentVariableTarget]::Machine);

ENV GOLANG_VERSION=1.17.6

RUN $url = 'https://dl.google.com/go/go1.17.6.windows-amd64.zip'; Write-Host ('Downloading {0} ...' -f $url); [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -Uri $url -OutFile 'go.zip'; $sha256 = '5bf8f87aec7edfc08e6bc845f1c30dba6de32b863f89ae46553ff4bbcc1d4954'; Write-Host ('Verifying sha256 ({0}) ...' -f $sha256); if ((Get-FileHash go.zip -Algorithm sha256).Hash -ne $sha256) { Write-Host 'FAILED!'; exit 1; }; Write-Host 'Expanding ...'; Expand-Archive go.zip -DestinationPath C:\; Write-Host 'Moving ...'; Move-Item -Path C:\go -Destination 'C:\Program Files\Go'; Write-Host 'Removing ...'; Remove-Item go.zip -Force; Write-Host 'Verifying install ("go version") ...'; go version; Write-Host 'Complete.';

COPY . /neo-go

Expand Down
91 changes: 79 additions & 12 deletions cli/server/server.go
Expand Up @@ -4,8 +4,10 @@ import (
"context"
"errors"
"fmt"
"net/url"
"os"
"os/signal"
"runtime"
"syscall"

"github.com/nspcc-dev/neo-go/cli/options"
Expand All @@ -29,6 +31,13 @@ import (
"go.uber.org/zap/zapcore"
)

var (
// _winfileSinkRegistered denotes whether zap has registered
// user-supplied factory for all sinks with `winfile`-prefixed scheme.
_winfileSinkRegistered bool
_winfileSinkCloser func() error
)

// NewCommands returns 'node' command.
func NewCommands() []cli.Command {
var cfgFlags = []cli.Flag{
Expand Down Expand Up @@ -124,7 +133,9 @@ func getConfigFromContext(ctx *cli.Context) (config.Config, error) {
// handleLoggingParams reads logging parameters.
// If user selected debug level -- function enables it.
// If logPath is configured -- function creates dir and file for logging.
func handleLoggingParams(ctx *cli.Context, cfg config.ApplicationConfiguration) (*zap.Logger, error) {
// If logPath is configured on Windows -- function returns closer to be
// able to close sink for opened log output file.
func handleLoggingParams(ctx *cli.Context, cfg config.ApplicationConfiguration) (*zap.Logger, func() error, error) {
level := zapcore.InfoLevel
if ctx.Bool("debug") {
level = zapcore.DebugLevel
Expand All @@ -142,13 +153,56 @@ func handleLoggingParams(ctx *cli.Context, cfg config.ApplicationConfiguration)

if logPath := cfg.LogPath; logPath != "" {
if err := io.MakeDirForFile(logPath, "logger"); err != nil {
return nil, err
return nil, nil, err
}

if runtime.GOOS == "windows" {
if !_winfileSinkRegistered {
// See https://github.com/uber-go/zap/issues/621.
err := zap.RegisterSink("winfile", func(u *url.URL) (zap.Sink, error) {
if u.User != nil {
return nil, fmt.Errorf("user and password not allowed with file URLs: got %v", u)
}
if u.Fragment != "" {
return nil, fmt.Errorf("fragments not allowed with file URLs: got %v", u)
}
if u.RawQuery != "" {
return nil, fmt.Errorf("query parameters not allowed with file URLs: got %v", u)
}
// Error messages are better if we check hostname and port separately.
if u.Port() != "" {
return nil, fmt.Errorf("ports not allowed with file URLs: got %v", u)
}
if hn := u.Hostname(); hn != "" && hn != "localhost" {
return nil, fmt.Errorf("file URLs must leave host empty or use localhost: got %v", u)
}
switch u.Path {
case "stdout":
return os.Stdout, nil
case "stderr":
return os.Stderr, nil
}
f, err := os.OpenFile(u.Path[1:], // Remove leading slash left after url.Parse.
os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644)
_winfileSinkCloser = func() error {
_winfileSinkCloser = nil
return f.Close()
}
return f, err
})
if err != nil {
return nil, nil, fmt.Errorf("failed to register windows-specific sinc: %w", err)
}
_winfileSinkRegistered = true
}
logPath = "winfile:///" + logPath
}

cc.OutputPaths = []string{logPath}
}

return cc.Build()
log, err := cc.Build()
return log, _winfileSinkCloser, err
}

func initBCWithMetrics(cfg config.Config, log *zap.Logger) (*core.Blockchain, *metrics.Service, *metrics.Service, error) {
Expand All @@ -172,10 +226,13 @@ func dumpDB(ctx *cli.Context) error {
if err != nil {
return cli.NewExitError(err, 1)
}
log, err := handleLoggingParams(ctx, cfg.ApplicationConfiguration)
log, logCloser, err := handleLoggingParams(ctx, cfg.ApplicationConfiguration)
if err != nil {
return cli.NewExitError(err, 1)
}
if logCloser != nil {
defer func() { _ = logCloser() }()
}
count := uint32(ctx.Uint("count"))
start := uint32(ctx.Uint("start"))

Expand Down Expand Up @@ -219,10 +276,13 @@ func restoreDB(ctx *cli.Context) error {
if err != nil {
return err
}
log, err := handleLoggingParams(ctx, cfg.ApplicationConfiguration)
log, logCloser, err := handleLoggingParams(ctx, cfg.ApplicationConfiguration)
if err != nil {
return cli.NewExitError(err, 1)
}
if logCloser != nil {
defer func() { _ = logCloser() }()
}
count := uint32(ctx.Uint("count"))

var inStream = os.Stdin
Expand All @@ -244,9 +304,11 @@ func restoreDB(ctx *cli.Context) error {
if err != nil {
return err
}
defer chain.Close()
defer prometheus.ShutDown()
defer pprof.ShutDown()
defer func() {
pprof.ShutDown()
prometheus.ShutDown()
chain.Close()
}()

var start uint32
if ctx.Bool("incremental") {
Expand Down Expand Up @@ -395,10 +457,13 @@ func startServer(ctx *cli.Context) error {
if err != nil {
return cli.NewExitError(err, 1)
}
log, err := handleLoggingParams(ctx, cfg.ApplicationConfiguration)
log, logCloser, err := handleLoggingParams(ctx, cfg.ApplicationConfiguration)
if err != nil {
return cli.NewExitError(err, 1)
}
if logCloser != nil {
defer func() { _ = logCloser() }()
}

grace, cancel := context.WithCancel(newGraceContext())
defer cancel()
Expand All @@ -409,6 +474,11 @@ func startServer(ctx *cli.Context) error {
if err != nil {
return cli.NewExitError(err, 1)
}
defer func() {
pprof.ShutDown()
prometheus.ShutDown()
chain.Close()
}()

serv, err := network.NewServer(serverConfig, chain, chain.GetStateSyncModule(), log)
if err != nil {
Expand Down Expand Up @@ -471,9 +541,6 @@ Main:
if serverErr := rpcServer.Shutdown(); serverErr != nil {
shutdownErr = fmt.Errorf("error on shutdown: %w", serverErr)
}
prometheus.ShutDown()
pprof.ShutDown()
chain.Close()
break Main
}
}
Expand Down
25 changes: 20 additions & 5 deletions cli/server/server_test.go
Expand Up @@ -41,7 +41,6 @@ func TestGetConfigFromContext(t *testing.T) {
}

func TestHandleLoggingParams(t *testing.T) {
// This test is failing on Windows, see https://github.com/nspcc-dev/neo-go/issues/2269
d := t.TempDir()
testLog := filepath.Join(d, "file.log")

Expand All @@ -53,8 +52,9 @@ func TestHandleLoggingParams(t *testing.T) {
cfg := config.ApplicationConfiguration{
LogPath: filepath.Join(logfile, "file.log"),
}
_, err := handleLoggingParams(ctx, cfg)
_, closer, err := handleLoggingParams(ctx, cfg)
require.Error(t, err)
require.Nil(t, closer)
})

t.Run("default", func(t *testing.T) {
Expand All @@ -63,8 +63,13 @@ func TestHandleLoggingParams(t *testing.T) {
cfg := config.ApplicationConfiguration{
LogPath: testLog,
}
logger, err := handleLoggingParams(ctx, cfg)
logger, closer, err := handleLoggingParams(ctx, cfg)
require.NoError(t, err)
t.Cleanup(func() {
if closer != nil {
require.NoError(t, closer())
}
})
require.True(t, logger.Core().Enabled(zap.InfoLevel))
require.False(t, logger.Core().Enabled(zap.DebugLevel))
})
Expand All @@ -76,8 +81,13 @@ func TestHandleLoggingParams(t *testing.T) {
cfg := config.ApplicationConfiguration{
LogPath: testLog,
}
logger, err := handleLoggingParams(ctx, cfg)
logger, closer, err := handleLoggingParams(ctx, cfg)
require.NoError(t, err)
t.Cleanup(func() {
if closer != nil {
require.NoError(t, closer())
}
})
require.True(t, logger.Core().Enabled(zap.InfoLevel))
require.True(t, logger.Core().Enabled(zap.DebugLevel))
})
Expand All @@ -96,8 +106,13 @@ func TestInitBCWithMetrics(t *testing.T) {
ctx := cli.NewContext(cli.NewApp(), set, nil)
cfg, err := getConfigFromContext(ctx)
require.NoError(t, err)
logger, err := handleLoggingParams(ctx, cfg.ApplicationConfiguration)
logger, closer, err := handleLoggingParams(ctx, cfg.ApplicationConfiguration)
require.NoError(t, err)
t.Cleanup(func() {
if closer != nil {
require.NoError(t, closer())
}
})

t.Run("bad store", func(t *testing.T) {
_, _, _, err = initBCWithMetrics(config.Config{}, logger)
Expand Down
50 changes: 27 additions & 23 deletions cli/server_test.go
@@ -1,11 +1,11 @@
package main

import (
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"runtime"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -96,29 +96,33 @@ func TestServerStart(t *testing.T) {
e.RunWithError(t, baseCmd...)
})
})
t.Run("good", func(t *testing.T) {
saveCfg(t, func(cfg *config.Config) {})
// We can't properly shutdown server on windows and release the resources.
// Also, windows doesn't support SIGHUP and SIGINT.
if runtime.GOOS != "windows" {
t.Run("good", func(t *testing.T) {
saveCfg(t, func(cfg *config.Config) {})

go func() {
e.Run(t, baseCmd...)
}()
go func() {
e.Run(t, baseCmd...)
}()

var line string
require.Eventually(t, func() bool {
line, err = e.Out.ReadString('\n')
if err != nil && err != io.EOF {
t.Fatalf(fmt.Sprintf("unexpected error while reading CLI output: %s", err))
var line string
require.Eventually(t, func() bool {
line, err = e.Out.ReadString('\n')
if err != nil && err != io.EOF {
t.Fatalf("unexpected error while reading CLI output: %s", err)
}
return err == nil
}, 2*time.Second, 100*time.Millisecond)
lines := strings.Split(server.Logo(), "\n")
for _, expected := range lines {
// It should be regexp, so escape all backslashes.
expected = strings.ReplaceAll(expected, `\`, `\\`)
e.checkLine(t, line, expected)
line = e.getNextLine(t)
}
return err == nil
}, 2*time.Second, 100*time.Millisecond)
lines := strings.Split(server.Logo(), "\n")
for _, expected := range lines {
// It should be regexp, so escape all backslashes.
expected = strings.ReplaceAll(expected, `\`, `\\`)
e.checkLine(t, line, expected)
line = e.getNextLine(t)
}
e.checkNextLine(t, "")
e.checkEOF(t)
})
e.checkNextLine(t, "")
e.checkEOF(t)
})
}
}
7 changes: 4 additions & 3 deletions pkg/compiler/analysis.go
Expand Up @@ -235,9 +235,10 @@ func (c *codegen) fillDocumentInfo() {
fset := c.buildInfo.config.Fset
fset.Iterate(func(f *token.File) bool {
filePath := f.Position(f.Pos(0)).Filename
filePath, err := filepath.Rel(c.buildInfo.config.Dir, filePath)
if err != nil {
panic(err)
rel, err := filepath.Rel(c.buildInfo.config.Dir, filePath)
// It's OK if we can't construct relative path, e.g. for interop dependencies.
if err == nil {
filePath = rel
}
c.docIndex[filePath] = len(c.documents)
c.documents = append(c.documents, filePath)
Expand Down
6 changes: 3 additions & 3 deletions pkg/network/server_test.go
Expand Up @@ -404,7 +404,7 @@ func TestBlock(t *testing.T) {
b := block.New(false)
b.Index = 12345
s.testHandleMessage(t, nil, CMDBlock, b)
require.Eventually(t, func() bool { return s.chain.BlockHeight() == 12345 }, time.Second, time.Millisecond*500)
require.Eventually(t, func() bool { return s.chain.BlockHeight() == 12345 }, 2*time.Second, time.Millisecond*500)
}

func TestConsensus(t *testing.T) {
Expand Down Expand Up @@ -497,8 +497,8 @@ func (s *Server) testHandleGetData(t *testing.T, invType payload.InventoryType,

s.testHandleMessage(t, p, CMDGetData, payload.NewInventory(invType, hs))

require.Eventually(t, func() bool { return recvResponse.Load() }, time.Second, time.Millisecond)
require.Eventually(t, func() bool { return recvNotFound.Load() }, time.Second, time.Millisecond)
require.Eventually(t, func() bool { return recvResponse.Load() }, 2*time.Second, time.Millisecond)
require.Eventually(t, func() bool { return recvNotFound.Load() }, 2*time.Second, time.Millisecond)
}

func TestGetData(t *testing.T) {
Expand Down

0 comments on commit acd348c

Please sign in to comment.