summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Titov <[email protected]>2020-03-02 11:45:50 +0300
committerGitHub <[email protected]>2020-03-02 11:45:50 +0300
commitb74aedd13ef6aa0bb78bc08bb521caa36e099e9d (patch)
treebb727c3105a082ece946142fde1696ce2e895067
parent9960aff462c985f89e1e9387e0b87bab24504d0e (diff)
parent456c9934a898fbbaf8e92e1b6bd815b6a8ffeffb (diff)
Merge pull request #260 from spiral/address_already_in_use_error
Address already in use error
-rw-r--r--.github/workflows/ci-build.yml175
-rw-r--r--go.mod1
-rw-r--r--go.sum2
-rw-r--r--pipe_factory_test.go4
-rw-r--r--service/headers/service_test.go28
-rw-r--r--service/http/fcgi_test.go8
-rw-r--r--service/http/h2c_test.go17
-rw-r--r--service/http/rpc_test.go44
-rw-r--r--service/http/service_test.go55
-rw-r--r--service/http/ssl_test.go48
-rw-r--r--service/limit/service_test.go91
-rw-r--r--service/reload/config_test.go2
-rw-r--r--service/reload/watcher_test.go3
-rw-r--r--service/rpc/config_test.go2
-rw-r--r--service/static/service_test.go21
-rw-r--r--socket_factory_test.go20
-rw-r--r--static_pool_test.go30
-rw-r--r--util/network.go15
-rw-r--r--util/network_test.go7
-rw-r--r--util/network_windows.go33
-rw-r--r--util/network_windows_test.go16
-rw-r--r--worker_test.go15
22 files changed, 382 insertions, 255 deletions
diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml
index b0977521..7c28ca76 100644
--- a/.github/workflows/ci-build.yml
+++ b/.github/workflows/ci-build.yml
@@ -4,100 +4,101 @@ on: [push, pull_request]
jobs:
build:
- name: Build (PHP ${{ matrix.php }}, Go ${{ matrix.go }})
- runs-on: ubuntu-latest
+ name: Build (PHP ${{ matrix.php }}, Go ${{ matrix.go }}, OS ${{ matrix.os }})
+ runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
php: [7.1, 7.2, 7.3, 7.4]
- go: [1.12, 1.13]
+ go: [1.13, 1.14]
+ os: [ubuntu-latest, macOS-latest]
env:
GO111MODULE: on
steps:
- - name: Set up Go ${{ matrix.go }}
- uses: actions/setup-go@v1
- with:
- go-version: ${{ matrix.go }}
-
- - name: Set up PHP ${{ matrix.php }}
- uses: shivammathur/setup-php@v1
- with:
- php-version: ${{ matrix.php }}
- extensions: dom
- coverage: xdebug
-
- - name: Check out code
- uses: actions/checkout@v2
- with:
- fetch-depth: 1
-
- - name: Show versions
- run: php -v && composer -V && go version
-
- - name: Debug if needed
- env:
- DEBUG: ${{ secrets.DEBUG }}
- run: if [[ "$DEBUG" == "true" ]]; then env && go env; fi
-
- - name: Syntax check only (lint)
- run: find ./src/ -name "*.php" -print0 | xargs -0 -n1 -P8 php -l
-
- - name: Get Composer Cache Directory # Docs: <https://github.com/actions/cache/blob/master/examples.md#php---composer>
- id: composer-cache
- run: echo "::set-output name=dir::$(composer config cache-files-dir)"
-
- - name: Cache dependencies # Docs: <https://github.com/actions/cache/blob/master/examples.md#php---composer>
- uses: actions/cache@v1
- with:
- path: ${{ steps.composer-cache.outputs.dir }}
- key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
- restore-keys: ${{ runner.os }}-composer-
-
- - name: Install Composer dependencies
- run: composer install --prefer-dist --no-interaction --no-suggest # --prefer-source
-
- - name: Analyze PHP sources
- run: composer analyze
-
- - name: Install Go dependencies
- run: go mod download
-
- - name: Download binary roadrunner
- run: php ./bin/rr get-binary
-
- - name: Run golang tests
- run: |
- go test -race -v -coverprofile=lib.txt -covermode=atomic
- go test ./util -race -v -coverprofile=util.txt -covermode=atomic
- go test ./service -race -v -coverprofile=service.txt -covermode=atomic
- go test ./service/env -race -v -coverprofile=env.txt -covermode=atomic
- go test ./service/rpc -race -v -coverprofile=rpc.txt -covermode=atomic
- go test ./service/http -race -v -coverprofile=http.txt -covermode=atomic
- go test ./service/static -race -v -coverprofile=static.txt -covermode=atomic
- go test ./service/limit -race -v -coverprofile=limit.txt -covermode=atomic
- go test ./service/headers -race -v -coverprofile=headers.txt -covermode=atomic
- go test ./service/metrics -race -v -coverprofile=metrics.txt -covermode=atomic
- go test ./service/health -race -v -coverprofile=health.txt -covermode=atomic
-
- - name: Run code coverage
- env:
- CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
- run: |
- if [[ "$CODECOV_TOKEN" != "" ]]; then
- curl https://codecov.io/bash -o codecov-bash
- chmod +x codecov-bash
- ./codecov-bash -f lib.txt
- ./codecov-bash -f util.txt
- ./codecov-bash -f service.txt
- ./codecov-bash -f env.txt
- ./codecov-bash -f rpc.txt
- ./codecov-bash -f http.txt
- ./codecov-bash -f static.txt
- ./codecov-bash -f limit.txt
- ./codecov-bash -f headers.txt
- ./codecov-bash -f metrics.txt
- ./codecov-bash -f health.txt
- fi
+ - name: Set up Go ${{ matrix.go }}
+ uses: actions/setup-go@v1
+ with:
+ go-version: ${{ matrix.go }}
+
+ - name: Set up PHP ${{ matrix.php }}
+ uses: shivammathur/setup-php@v1
+ with:
+ php-version: ${{ matrix.php }}
+ extensions: dom
+ coverage: xdebug
+
+ - name: Check out code
+ uses: actions/checkout@v2
+ with:
+ fetch-depth: 1
+
+ - name: Show versions
+ run: php -v ; composer -V ; go version
+
+ - name: Debug if needed
+ env:
+ DEBUG: ${{ secrets.DEBUG }}
+ run: if [[ "$DEBUG" == "true" ]]; then env && go env; fi
+
+ - name: Syntax check only (lint)
+ run: find ./src/ -name "*.php" -print0 | xargs -0 -n1 -P8 php -l
+
+ - name: Get Composer Cache Directory # Docs: <https://github.com/actions/cache/blob/master/examples.md#php---composer>
+ id: composer-cache
+ run: echo "::set-output name=dir::$(composer config cache-files-dir)"
+
+ - name: Cache dependencies # Docs: <https://github.com/actions/cache/blob/master/examples.md#php---composer>
+ uses: actions/cache@v1
+ with:
+ path: ${{ steps.composer-cache.outputs.dir }}
+ key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
+ restore-keys: ${{ runner.os }}-composer-
+
+ - name: Install Composer dependencies
+ run: composer install --prefer-dist --no-interaction --no-suggest # --prefer-source
+
+ - name: Analyze PHP sources
+ run: composer analyze
+
+ - name: Install Go dependencies
+ run: go mod download
+
+ - name: Download binary roadrunner
+ run: php ./bin/rr get-binary
+
+ - name: Run golang tests
+ run: |
+ go test -race -v -coverprofile=lib.txt -covermode=atomic
+ go test ./util -race -v -coverprofile=util.txt -covermode=atomic
+ go test ./service -race -v -coverprofile=service.txt -covermode=atomic
+ go test ./service/env -race -v -coverprofile=env.txt -covermode=atomic
+ go test ./service/rpc -race -v -coverprofile=rpc.txt -covermode=atomic
+ go test ./service/http -race -v -coverprofile=http.txt -covermode=atomic
+ go test ./service/static -race -v -coverprofile=static.txt -covermode=atomic
+ go test ./service/limit -race -v -coverprofile=limit.txt -covermode=atomic
+ go test ./service/headers -race -v -coverprofile=headers.txt -covermode=atomic
+ go test ./service/metrics -race -v -coverprofile=metrics.txt -covermode=atomic
+ go test ./service/health -race -v -coverprofile=health.txt -covermode=atomic
+
+ - name: Run code coverage
+ env:
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
+ run: |
+ if [[ "$CODECOV_TOKEN" != "" ]]; then
+ curl https://codecov.io/bash -o codecov-bash
+ chmod +x codecov-bash
+ ./codecov-bash -f lib.txt
+ ./codecov-bash -f util.txt
+ ./codecov-bash -f service.txt
+ ./codecov-bash -f env.txt
+ ./codecov-bash -f rpc.txt
+ ./codecov-bash -f http.txt
+ ./codecov-bash -f static.txt
+ ./codecov-bash -f limit.txt
+ ./codecov-bash -f headers.txt
+ ./codecov-bash -f metrics.txt
+ ./codecov-bash -f health.txt
+ fi
golangci-check:
name: runner / golangci-lint
diff --git a/go.mod b/go.mod
index 79a26d32..a3edb246 100644
--- a/go.mod
+++ b/go.mod
@@ -19,6 +19,7 @@ require (
github.com/spf13/viper v1.6.2
github.com/spiral/goridge v2.1.4+incompatible
github.com/stretchr/testify v1.5.1
+ github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a
github.com/yookoala/gofast v0.4.0
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0
)
diff --git a/go.sum b/go.sum
index c3c717be..f0e1428c 100644
--- a/go.sum
+++ b/go.sum
@@ -194,6 +194,8 @@ github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
+github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a h1:0R4NLDRDZX6JcmhJgXi5E4b8Wg84ihbmUKp/GvSPEzc=
+github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yookoala/gofast v0.4.0 h1:dLBjghcsbbZNOEHN8N1X/gh9S6srmJed4WQfG7DlKwo=
diff --git a/pipe_factory_test.go b/pipe_factory_test.go
index 27d1f74d..14cf1272 100644
--- a/pipe_factory_test.go
+++ b/pipe_factory_test.go
@@ -4,6 +4,7 @@ import (
"github.com/stretchr/testify/assert"
"os/exec"
"testing"
+ "time"
)
func Test_Pipe_Start(t *testing.T) {
@@ -108,8 +109,9 @@ func Test_Pipe_Broken(t *testing.T) {
assert.Contains(t, err.Error(), "undefined_function()")
}()
defer func() {
+ time.Sleep(time.Second)
err := w.Stop()
- assert.Error(t, err)
+ assert.NoError(t, err)
}()
res, err := w.Exec(&Payload{Body: []byte("hello")})
diff --git a/service/headers/service_test.go b/service/headers/service_test.go
index 2f29db5e..120bb3d6 100644
--- a/service/headers/service_test.go
+++ b/service/headers/service_test.go
@@ -46,7 +46,7 @@ func Test_RequestHeaders(t *testing.T) {
headers: `{"request":{"input": "custom-header"}}`,
httpCfg: `{
"enable": true,
- "address": ":6029",
+ "address": ":6078",
"maxRequestSize": 1024,
"workers":{
"command": "php ../../tests/http/client.php header pipes",
@@ -68,7 +68,7 @@ func Test_RequestHeaders(t *testing.T) {
time.Sleep(time.Millisecond * 100)
defer c.Stop()
- req, err := http.NewRequest("GET", "http://localhost:6029?hello=value", nil)
+ req, err := http.NewRequest("GET", "http://localhost:6078?hello=value", nil)
assert.NoError(t, err)
r, err := http.DefaultClient.Do(req)
@@ -100,7 +100,7 @@ func Test_ResponseHeaders(t *testing.T) {
headers: `{"response":{"output": "output-header"},"request":{"input": "custom-header"}}`,
httpCfg: `{
"enable": true,
- "address": ":6029",
+ "address": ":6079",
"maxRequestSize": 1024,
"workers":{
"command": "php ../../tests/http/client.php header pipes",
@@ -122,7 +122,7 @@ func Test_ResponseHeaders(t *testing.T) {
time.Sleep(time.Millisecond * 100)
defer c.Stop()
- req, err := http.NewRequest("GET", "http://localhost:6029?hello=value", nil)
+ req, err := http.NewRequest("GET", "http://localhost:6079?hello=value", nil)
assert.NoError(t, err)
r, err := http.DefaultClient.Do(req)
@@ -164,7 +164,7 @@ func TestCORS_OPTIONS(t *testing.T) {
}`,
httpCfg: `{
"enable": true,
- "address": ":6029",
+ "address": ":6379",
"maxRequestSize": 1024,
"workers":{
"command": "php ../../tests/http/client.php headers pipes",
@@ -186,7 +186,7 @@ func TestCORS_OPTIONS(t *testing.T) {
time.Sleep(time.Millisecond * 100)
defer c.Stop()
- req, err := http.NewRequest("OPTIONS", "http://localhost:6029", nil)
+ req, err := http.NewRequest("OPTIONS", "http://localhost:6379", nil)
assert.NoError(t, err)
r, err := http.DefaultClient.Do(req)
@@ -232,7 +232,7 @@ func TestCORS_Pass(t *testing.T) {
}`,
httpCfg: `{
"enable": true,
- "address": ":6029",
+ "address": ":6672",
"maxRequestSize": 1024,
"workers":{
"command": "php ../../tests/http/client.php headers pipes",
@@ -254,18 +254,11 @@ func TestCORS_Pass(t *testing.T) {
time.Sleep(time.Millisecond * 100)
defer c.Stop()
- req, err := http.NewRequest("GET", "http://localhost:6029", nil)
+ req, err := http.NewRequest("GET", "http://localhost:6672", nil)
assert.NoError(t, err)
r, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
- defer func() {
- err := r.Body.Close()
- if err != nil {
- t.Errorf("error during the body closing: error %v", err)
- }
- }()
-
assert.Equal(t, "true", r.Header.Get("Access-Control-Allow-Credentials"))
assert.Equal(t, "*", r.Header.Get("Access-Control-Allow-Headers"))
assert.Equal(t, "*", r.Header.Get("Access-Control-Allow-Origin"))
@@ -275,4 +268,9 @@ func TestCORS_Pass(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, 200, r.StatusCode)
+
+ err = r.Body.Close()
+ if err != nil {
+ t.Errorf("error during the body closing: error %v", err)
+ }
}
diff --git a/service/http/fcgi_test.go b/service/http/fcgi_test.go
index 0cfc6e41..e68b2e7f 100644
--- a/service/http/fcgi_test.go
+++ b/service/http/fcgi_test.go
@@ -37,8 +37,7 @@ func Test_FCGI_Service_Echo(t *testing.T) {
s.(*Service).Stop()
go func() { assert.NoError(t, c.Serve()) }()
- time.Sleep(time.Millisecond * 100)
- defer c.Stop()
+ time.Sleep(time.Second * 1)
fcgiConnFactory := gofast.SimpleConnFactory("tcp", "0.0.0.0:6082")
@@ -56,6 +55,7 @@ func Test_FCGI_Service_Echo(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, 201, w.Result().StatusCode)
assert.Equal(t, "WORLD", string(body))
+ c.Stop()
}
func Test_FCGI_Service_Request_Uri(t *testing.T) {
@@ -83,8 +83,7 @@ func Test_FCGI_Service_Request_Uri(t *testing.T) {
s.(*Service).Stop()
go func() { assert.NoError(t, c.Serve()) }()
- time.Sleep(time.Millisecond * 100)
- defer c.Stop()
+ time.Sleep(time.Second * 1)
fcgiConnFactory := gofast.SimpleConnFactory("tcp", "0.0.0.0:6083")
@@ -102,4 +101,5 @@ func Test_FCGI_Service_Request_Uri(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, 200, w.Result().StatusCode)
assert.Equal(t, "http://site.local/hello-world", string(body))
+ c.Stop()
}
diff --git a/service/http/h2c_test.go b/service/http/h2c_test.go
index 7bbc30ac..a2465a0a 100644
--- a/service/http/h2c_test.go
+++ b/service/http/h2c_test.go
@@ -52,16 +52,15 @@ func Test_Service_H2C(t *testing.T) {
req.Header.Add("Connection", "HTTP2-Settings")
req.Header.Add("HTTP2-Settings", "")
- r, err := http.DefaultClient.Do(req)
- assert.NoError(t, err)
- defer func() {
- err := r.Body.Close()
- if err != nil {
- t.Errorf("fail to close the Body: error %v", err)
- }
- }()
+ r, err2 := http.DefaultClient.Do(req)
+ if err2 != nil {
+ t.Fatal(err2)
+ }
assert.Equal(t, "101 Switching Protocols", r.Status)
- // will fail with h2c notice
+ err3 := r.Body.Close()
+ if err3 != nil {
+ t.Errorf("fail to close the Body: error %v", err3)
+ }
}
diff --git a/service/http/rpc_test.go b/service/http/rpc_test.go
index 0e4b2c0a..1971f237 100644
--- a/service/http/rpc_test.go
+++ b/service/http/rpc_test.go
@@ -55,10 +55,13 @@ func Test_RPC(t *testing.T) {
t.Errorf("error during the Serve: error %v", err)
}
}()
- time.Sleep(time.Millisecond * 100)
- defer c.Stop()
- res, _, _ := get("http://localhost:6029")
+ time.Sleep(time.Second)
+
+ res, _, err := get("http://localhost:6029")
+ if err != nil {
+ t.Fatal(err)
+ }
assert.Equal(t, strconv.Itoa(*ss.rr.Workers()[0].Pid), res)
cl, err := rs.Client()
@@ -68,9 +71,13 @@ func Test_RPC(t *testing.T) {
assert.NoError(t, cl.Call("http.Reset", true, &r))
assert.Equal(t, "OK", r)
- res2, _, _ := get("http://localhost:6029")
+ res2, _, err := get("http://localhost:6029")
+ if err != nil {
+ t.Fatal()
+ }
assert.Equal(t, strconv.Itoa(*ss.rr.Workers()[0].Pid), res2)
assert.NotEqual(t, res, res2)
+ c.Stop()
}
func Test_RPC_Unix(t *testing.T) {
@@ -121,22 +128,39 @@ func Test_RPC_Unix(t *testing.T) {
t.Errorf("error during the Serve: error %v", err)
}
}()
- time.Sleep(time.Millisecond * 100)
- defer c.Stop()
- res, _, _ := get("http://localhost:6029")
- assert.Equal(t, strconv.Itoa(*ss.rr.Workers()[0].Pid), res)
+ time.Sleep(time.Second)
+
+ res, _, err := get("http://localhost:6029")
+ if err != nil {
+ c.Stop()
+ t.Fatal(err)
+ }
+ if ss.rr.Workers() != nil && len(ss.rr.Workers()) > 0 {
+ assert.Equal(t, strconv.Itoa(*ss.rr.Workers()[0].Pid), res)
+ } else {
+ c.Stop()
+ t.Fatal("no workers initialized")
+ }
cl, err := rs.Client()
- assert.NoError(t, err)
+ if err != nil {
+ c.Stop()
+ t.Fatal(err)
+ }
r := ""
assert.NoError(t, cl.Call("http.Reset", true, &r))
assert.Equal(t, "OK", r)
- res2, _, _ := get("http://localhost:6029")
+ res2, _, err := get("http://localhost:6029")
+ if err != nil {
+ c.Stop()
+ t.Fatal(err)
+ }
assert.Equal(t, strconv.Itoa(*ss.rr.Workers()[0].Pid), res2)
assert.NotEqual(t, res, res2)
+ c.Stop()
}
func Test_Workers(t *testing.T) {
diff --git a/service/http/service_test.go b/service/http/service_test.go
index c4b2c2c4..1a1c32ae 100644
--- a/service/http/service_test.go
+++ b/service/http/service_test.go
@@ -115,7 +115,7 @@ func Test_Service_Echo(t *testing.T) {
assert.NoError(t, c.Init(&testCfg{httpCfg: `{
"enable": true,
- "address": ":6029",
+ "address": ":6536",
"maxRequestSize": 1024,
"uploads": {
"dir": ` + tmpDir() + `,
@@ -146,26 +146,24 @@ func Test_Service_Echo(t *testing.T) {
}
}()
time.Sleep(time.Millisecond * 100)
- defer c.Stop()
- req, err := http.NewRequest("GET", "http://localhost:6029?hello=world", nil)
+ req, err := http.NewRequest("GET", "http://localhost:6536?hello=world", nil)
assert.NoError(t, err)
r, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
- defer func() {
- err := r.Body.Close()
- if err != nil {
- t.Errorf("error closing the Body: error %v", err)
- }
- }()
-
b, err := ioutil.ReadAll(r.Body)
assert.NoError(t, err)
assert.NoError(t, err)
assert.Equal(t, 201, r.StatusCode)
assert.Equal(t, "WORLD", string(b))
+
+ err2 := r.Body.Close()
+ if err2 != nil {
+ t.Errorf("error closing the Body: error %v", err2)
+ }
+ c.Stop()
}
func Test_Service_Env(t *testing.T) {
@@ -178,7 +176,7 @@ func Test_Service_Env(t *testing.T) {
assert.NoError(t, c.Init(&testCfg{httpCfg: `{
"enable": true,
- "address": ":6029",
+ "address": ":6031",
"maxRequestSize": 1024,
"uploads": {
"dir": ` + tmpDir() + `,
@@ -208,10 +206,10 @@ func Test_Service_Env(t *testing.T) {
t.Errorf("serve error: %v", err)
}
}()
- time.Sleep(time.Millisecond * 100)
- defer c.Stop()
- req, err := http.NewRequest("GET", "http://localhost:6029", nil)
+ time.Sleep(time.Second * 1)
+
+ req, err := http.NewRequest("GET", "http://localhost:6031", nil)
assert.NoError(t, err)
r, err := http.DefaultClient.Do(req)
@@ -229,6 +227,7 @@ func Test_Service_Env(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, 200, r.StatusCode)
assert.Equal(t, "ENV_VALUE", string(b))
+ c.Stop()
}
func Test_Service_ErrorEcho(t *testing.T) {
@@ -240,7 +239,7 @@ func Test_Service_ErrorEcho(t *testing.T) {
assert.NoError(t, c.Init(&testCfg{httpCfg: `{
"enable": true,
- "address": ":6029",
+ "address": ":6030",
"maxRequestSize": 1024,
"uploads": {
"dir": ` + tmpDir() + `,
@@ -276,10 +275,10 @@ func Test_Service_ErrorEcho(t *testing.T) {
t.Errorf("serve error: %v", err)
}
}()
- time.Sleep(time.Millisecond * 100)
- defer c.Stop()
- req, err := http.NewRequest("GET", "http://localhost:6029?hello=world", nil)
+ time.Sleep(time.Second)
+
+ req, err := http.NewRequest("GET", "http://localhost:6030?hello=world", nil)
assert.NoError(t, err)
r, err := http.DefaultClient.Do(req)
@@ -299,6 +298,7 @@ func Test_Service_ErrorEcho(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, 201, r.StatusCode)
assert.Equal(t, "WORLD", string(b))
+ c.Stop()
}
func Test_Service_Middleware(t *testing.T) {
@@ -310,7 +310,7 @@ func Test_Service_Middleware(t *testing.T) {
assert.NoError(t, c.Init(&testCfg{httpCfg: `{
"enable": true,
- "address": ":6029",
+ "address": ":6032",
"maxRequestSize": 1024,
"uploads": {
"dir": ` + tmpDir() + `,
@@ -351,10 +351,9 @@ func Test_Service_Middleware(t *testing.T) {
t.Errorf("serve error: %v", err)
}
}()
- time.Sleep(time.Millisecond * 100)
- defer c.Stop()
+ time.Sleep(time.Second)
- req, err := http.NewRequest("GET", "http://localhost:6029?hello=world", nil)
+ req, err := http.NewRequest("GET", "http://localhost:6032?hello=world", nil)
assert.NoError(t, err)
r, err := http.DefaultClient.Do(req)
@@ -372,7 +371,7 @@ func Test_Service_Middleware(t *testing.T) {
t.Errorf("error closing the Body: error %v", err)
}
- req, err = http.NewRequest("GET", "http://localhost:6029/halt", nil)
+ req, err = http.NewRequest("GET", "http://localhost:6032/halt", nil)
assert.NoError(t, err)
r, err = http.DefaultClient.Do(req)
@@ -386,8 +385,10 @@ func Test_Service_Middleware(t *testing.T) {
err = r.Body.Close()
if err != nil {
+ c.Stop()
t.Errorf("error closing the Body: error %v", err)
}
+ c.Stop()
}
func Test_Service_Listener(t *testing.T) {
@@ -399,7 +400,7 @@ func Test_Service_Listener(t *testing.T) {
assert.NoError(t, c.Init(&testCfg{httpCfg: `{
"enable": true,
- "address": ":6029",
+ "address": ":6033",
"maxRequestSize": 1024,
"uploads": {
"dir": ` + tmpDir() + `,
@@ -448,7 +449,7 @@ func Test_Service_Error(t *testing.T) {
assert.NoError(t, c.Init(&testCfg{httpCfg: `{
"enable": true,
- "address": ":6029",
+ "address": ":6034",
"maxRequestSize": 1024,
"uploads": {
"dir": ` + tmpDir() + `,
@@ -477,7 +478,7 @@ func Test_Service_Error2(t *testing.T) {
assert.NoError(t, c.Init(&testCfg{httpCfg: `{
"enable": true,
- "address": ":6029",
+ "address": ":6035",
"maxRequestSize": 1024,
"uploads": {
"dir": ` + tmpDir() + `,
@@ -506,7 +507,7 @@ func Test_Service_Error3(t *testing.T) {
assert.Error(t, c.Init(&testCfg{httpCfg: `{
"enable": true,
- "address": ":6029",
+ "address": ":6036",
"maxRequestSize": 1024,
"uploads": {
"dir": ` + tmpDir() + `,
diff --git a/service/http/ssl_test.go b/service/http/ssl_test.go
index 49bba6cb..b82aa75c 100644
--- a/service/http/ssl_test.go
+++ b/service/http/ssl_test.go
@@ -84,9 +84,9 @@ func Test_SSL_Service_NoRedirect(t *testing.T) {
c.Register(ID, &Service{})
assert.NoError(t, c.Init(&testCfg{httpCfg: `{
- "address": ":6029",
+ "address": ":6030",
"ssl": {
- "port": 6900,
+ "port": 6901,
"key": "fixtures/server.key",
"cert": "fixtures/server.crt"
},
@@ -109,19 +109,16 @@ func Test_SSL_Service_NoRedirect(t *testing.T) {
t.Errorf("error during the Serve: error %v", err)
}
}()
- time.Sleep(time.Millisecond * 100)
- defer c.Stop()
- req, err := http.NewRequest("GET", "http://localhost:6029?hello=world", nil)
+ time.Sleep(time.Second)
+
+ req, err := http.NewRequest("GET", "http://localhost:6030?hello=world", nil)
assert.NoError(t, err)
r, err := sslClient.Do(req)
assert.NoError(t, err)
defer func() {
- err := r.Body.Close()
- if err != nil {
- t.Errorf("fail to close the Body: error %v", err)
- }
+
}()
assert.Nil(t, r.TLS)
@@ -132,6 +129,12 @@ func Test_SSL_Service_NoRedirect(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, 201, r.StatusCode)
assert.Equal(t, "WORLD", string(b))
+
+ err2 := r.Body.Close()
+ if err2 != nil {
+ t.Errorf("fail to close the Body: error %v", err2)
+ }
+ c.Stop()
}
func Test_SSL_Service_Redirect(t *testing.T) {
@@ -142,9 +145,9 @@ func Test_SSL_Service_Redirect(t *testing.T) {
c.Register(ID, &Service{})
assert.NoError(t, c.Init(&testCfg{httpCfg: `{
- "address": ":6029",
+ "address": ":6031",
"ssl": {
- "port": 6900,
+ "port": 6902,
"redirect": true,
"key": "fixtures/server.key",
"cert": "fixtures/server.crt"
@@ -168,19 +171,16 @@ func Test_SSL_Service_Redirect(t *testing.T) {
t.Errorf("error during the Serve: error %v", err)
}
}()
- time.Sleep(time.Millisecond * 100)
- defer c.Stop()
- req, err := http.NewRequest("GET", "http://localhost:6029?hello=world", nil)
+ time.Sleep(time.Second)
+
+ req, err := http.NewRequest("GET", "http://localhost:6031?hello=world", nil)
assert.NoError(t, err)
r, err := sslClient.Do(req)
assert.NoError(t, err)
defer func() {
- err := r.Body.Close()
- if err != nil {
- t.Errorf("fail to close the Body: error %v", err)
- }
+
}()
assert.NotNil(t, r.TLS)
@@ -191,6 +191,12 @@ func Test_SSL_Service_Redirect(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, 201, r.StatusCode)
assert.Equal(t, "WORLD", string(b))
+
+ err2 := r.Body.Close()
+ if err2 != nil {
+ t.Errorf("fail to close the Body: error %v", err2)
+ }
+ c.Stop()
}
func Test_SSL_Service_Push(t *testing.T) {
@@ -201,9 +207,9 @@ func Test_SSL_Service_Push(t *testing.T) {
c.Register(ID, &Service{})
assert.NoError(t, c.Init(&testCfg{httpCfg: `{
- "address": ":6029",
+ "address": ":6032",
"ssl": {
- "port": 6900,
+ "port": 6903,
"redirect": true,
"key": "fixtures/server.key",
"cert": "fixtures/server.crt"
@@ -230,7 +236,7 @@ func Test_SSL_Service_Push(t *testing.T) {
time.Sleep(time.Millisecond * 100)
defer c.Stop()
- req, err := http.NewRequest("GET", "https://localhost:6900?hello=world", nil)
+ req, err := http.NewRequest("GET", "https://localhost:6903?hello=world", nil)
assert.NoError(t, err)
r, err := sslClient.Do(req)
diff --git a/service/limit/service_test.go b/service/limit/service_test.go
index 8cb3d7dc..abc03e69 100644
--- a/service/limit/service_test.go
+++ b/service/limit/service_test.go
@@ -57,7 +57,7 @@ func Test_Service_PidEcho(t *testing.T) {
assert.NoError(t, c.Init(&testCfg{
httpCfg: `{
- "address": ":6029",
+ "address": ":7029",
"workers":{
"command": "php ../../tests/http/client.php pid pipes",
"pool": {"numWorkers": 1}
@@ -81,26 +81,26 @@ func Test_Service_PidEcho(t *testing.T) {
t.Errorf("error during the Serve: error %v", err)
}
}()
- time.Sleep(time.Millisecond * 100)
- defer c.Stop()
- req, err := http.NewRequest("GET", "http://localhost:6029", nil)
+ time.Sleep(time.Millisecond * 100)
+ req, err := http.NewRequest("GET", "http://localhost:7029", nil)
assert.NoError(t, err)
r, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
- defer func() {
- err := r.Body.Close()
- if err != nil {
- t.Errorf("error during the body closing: error %v", err)
- }
- }()
+
b, err := ioutil.ReadAll(r.Body)
assert.NoError(t, err)
assert.NoError(t, err)
assert.Equal(t, getPID(s), string(b))
+
+ err2 := r.Body.Close()
+ if err2 != nil {
+ t.Errorf("error during the body closing: error %v", err2)
+ }
+ c.Stop()
}
func Test_Service_ListenerPlusTTL(t *testing.T) {
@@ -113,7 +113,7 @@ func Test_Service_ListenerPlusTTL(t *testing.T) {
assert.NoError(t, c.Init(&testCfg{
httpCfg: `{
- "address": ":6029",
+ "address": ":7030",
"workers":{
"command": "php ../../tests/http/client.php pid pipes",
"pool": {"numWorkers": 1}
@@ -145,22 +145,18 @@ func Test_Service_ListenerPlusTTL(t *testing.T) {
t.Errorf("error during the Serve: error %v", err)
}
}()
+
+
time.Sleep(time.Millisecond * 100)
- defer c.Stop()
lastPID := getPID(s)
- req, err := http.NewRequest("GET", "http://localhost:6029", nil)
+ req, err := http.NewRequest("GET", "http://localhost:7030", nil)
assert.NoError(t, err)
r, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
- defer func() {
- err := r.Body.Close()
- if err != nil {
- t.Errorf("error during the body closing: error %v", err)
- }
- }()
+
b, err := ioutil.ReadAll(r.Body)
assert.NoError(t, err)
@@ -169,13 +165,20 @@ func Test_Service_ListenerPlusTTL(t *testing.T) {
<-captured
// clean state
- req, err = http.NewRequest("GET", "http://localhost:6029?new", nil)
+ req, err = http.NewRequest("GET", "http://localhost:7030?new", nil)
assert.NoError(t, err)
_, err = http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotEqual(t, lastPID, getPID(s))
+
+ c.Stop()
+
+ err2 := r.Body.Close()
+ if err2 != nil {
+ t.Errorf("error during the body closing: error %v", err2)
+ }
}
func Test_Service_ListenerPlusIdleTTL(t *testing.T) {
@@ -188,7 +191,7 @@ func Test_Service_ListenerPlusIdleTTL(t *testing.T) {
assert.NoError(t, c.Init(&testCfg{
httpCfg: `{
- "address": ":6029",
+ "address": ":7031",
"workers":{
"command": "php ../../tests/http/client.php pid pipes",
"pool": {"numWorkers": 1}
@@ -220,22 +223,17 @@ func Test_Service_ListenerPlusIdleTTL(t *testing.T) {
t.Errorf("error during the Serve: error %v", err)
}
}()
+
+
time.Sleep(time.Millisecond * 100)
- defer c.Stop()
lastPID := getPID(s)
- req, err := http.NewRequest("GET", "http://localhost:6029", nil)
+ req, err := http.NewRequest("GET", "http://localhost:7031", nil)
assert.NoError(t, err)
r, err := http.DefaultClient.Do(req)
assert.NoError(t, err)
- defer func() {
- err := r.Body.Close()
- if err != nil {
- t.Errorf("error during the body closing: error %v", err)
- }
- }()
b, err := ioutil.ReadAll(r.Body)
assert.NoError(t, err)
@@ -246,13 +244,19 @@ func Test_Service_ListenerPlusIdleTTL(t *testing.T) {
<-captured
// clean state
- req, err = http.NewRequest("GET", "http://localhost:6029?new", nil)
+ req, err = http.NewRequest("GET", "http://localhost:7031?new", nil)
assert.NoError(t, err)
_, err = http.DefaultClient.Do(req)
assert.NoError(t, err)
assert.NotEqual(t, lastPID, getPID(s))
+
+ c.Stop()
+ err2 := r.Body.Close()
+ if err2 != nil {
+ t.Errorf("error during the body closing: error %v", err2)
+ }
}
func Test_Service_Listener_MaxExecTTL(t *testing.T) {
@@ -265,7 +269,7 @@ func Test_Service_Listener_MaxExecTTL(t *testing.T) {
assert.NoError(t, c.Init(&testCfg{
httpCfg: `{
- "address": ":6029",
+ "address": ":7032",
"workers":{
"command": "php ../../tests/http/client.php stuck pipes",
"pool": {"numWorkers": 1}
@@ -297,10 +301,10 @@ func Test_Service_Listener_MaxExecTTL(t *testing.T) {
t.Errorf("error during the Serve: error %v", err)
}
}()
+
time.Sleep(time.Millisecond * 100)
- defer c.Stop()
- req, err := http.NewRequest("GET", "http://localhost:6029", nil)
+ req, err := http.NewRequest("GET", "http://localhost:7032", nil)
assert.NoError(t, err)
r, err := http.DefaultClient.Do(req)
@@ -308,6 +312,8 @@ func Test_Service_Listener_MaxExecTTL(t *testing.T) {
assert.Equal(t, 500, r.StatusCode)
<-captured
+
+ c.Stop()
}
func Test_Service_Listener_MaxMemoryUsage(t *testing.T) {
@@ -320,7 +326,7 @@ func Test_Service_Listener_MaxMemoryUsage(t *testing.T) {
assert.NoError(t, c.Init(&testCfg{
httpCfg: `{
- "address": ":6029",
+ "address": ":7033",
"workers":{
"command": "php ../../tests/http/client.php memleak pipes",
"pool": {"numWorkers": 1}
@@ -354,12 +360,12 @@ func Test_Service_Listener_MaxMemoryUsage(t *testing.T) {
t.Errorf("error during the Serve: error %v", err)
}
}()
+
time.Sleep(time.Millisecond * 100)
- defer c.Stop()
lastPID := getPID(s)
- req, err := http.NewRequest("GET", "http://localhost:6029", nil)
+ req, err := http.NewRequest("GET", "http://localhost:7033", nil)
assert.NoError(t, err)
for {
@@ -367,19 +373,28 @@ func Test_Service_Listener_MaxMemoryUsage(t *testing.T) {
case <-captured:
_, err := http.DefaultClient.Do(req)
if err != nil {
+ c.Stop()
t.Errorf("error during sending the http request: error %v", err)
}
assert.NotEqual(t, lastPID, getPID(s))
+ c.Stop()
return
default:
_, err := http.DefaultClient.Do(req)
if err != nil {
+ c.Stop()
t.Errorf("error during sending the http request: error %v", err)
}
+ c.Stop()
+ return
}
}
}
func getPID(s interface{}) string {
- w := s.(*rrhttp.Service).Server().Workers()[0]
- return fmt.Sprintf("%v", *w.Pid)
+ if len(s.(*rrhttp.Service).Server().Workers()) > 0 {
+ w := s.(*rrhttp.Service).Server().Workers()[0]
+ return fmt.Sprintf("%v", *w.Pid)
+ } else {
+ panic("no workers")
+ }
}
diff --git a/service/reload/config_test.go b/service/reload/config_test.go
index b7e6e669..600975d3 100644
--- a/service/reload/config_test.go
+++ b/service/reload/config_test.go
@@ -27,7 +27,7 @@ func Test_Config_Valid(t *testing.T) {
func Test_Fake_ServiceConfig(t *testing.T) {
services := make(map[string]ServiceConfig)
cfg := &Config{
- Interval: time.Second,
+ Interval: time.Microsecond,
Patterns: nil,
Services: services,
}
diff --git a/service/reload/watcher_test.go b/service/reload/watcher_test.go
index f5a5db01..391f6bb9 100644
--- a/service/reload/watcher_test.go
+++ b/service/reload/watcher_test.go
@@ -129,7 +129,6 @@ func Test_Get_FileEvent(t *testing.T) {
panic("didn't handle event when write file2")
}
w.Stop()
- return
}
}()
}()
@@ -224,7 +223,7 @@ func Test_FileExtensionFilter(t *testing.T) {
}
}()
w.Stop()
- return
+ runtime.Goexit()
}()
err = w.StartPolling(time.Second)
diff --git a/service/rpc/config_test.go b/service/rpc/config_test.go
index c65e7415..623347ed 100644
--- a/service/rpc/config_test.go
+++ b/service/rpc/config_test.go
@@ -48,7 +48,7 @@ func TestConfig_Listener(t *testing.T) {
}()
assert.Equal(t, "tcp", ln.Addr().Network())
- assert.Equal(t, "[::]:18001", ln.Addr().String())
+ assert.Equal(t, "0.0.0.0:18001", ln.Addr().String())
}
func TestConfig_ListenerUnix(t *testing.T) {
diff --git a/service/static/service_test.go b/service/static/service_test.go
index 4205650d..bcda26ce 100644
--- a/service/static/service_test.go
+++ b/service/static/service_test.go
@@ -90,11 +90,13 @@ func Test_Files(t *testing.T) {
t.Errorf("serve error: %v", err)
}
}()
- time.Sleep(time.Millisecond * 100)
- defer c.Stop()
+
+ time.Sleep(time.Second)
+
b, _, _ := get("http://localhost:6029/sample.txt")
assert.Equal(t, "sample", b)
+ c.Stop()
}
func Test_Disabled(t *testing.T) {
@@ -334,11 +336,12 @@ func Test_Files_NotFound(t *testing.T) {
t.Errorf("serve error: %v", err)
}
}()
- time.Sleep(time.Millisecond * 100)
- defer c.Stop()
+
+ time.Sleep(time.Second)
b, _, _ := get("http://localhost:6029/client.XXX?hello=world")
assert.Equal(t, "WORLD", b)
+ c.Stop()
}
func Test_Files_Dir(t *testing.T) {
@@ -376,11 +379,11 @@ func Test_Files_Dir(t *testing.T) {
t.Errorf("serve error: %v", err)
}
}()
- time.Sleep(time.Millisecond * 100)
- defer c.Stop()
+ time.Sleep(time.Second)
b, _, _ := get("http://localhost:6029/http?hello=world")
assert.Equal(t, "WORLD", b)
+ c.Stop()
}
func Test_Files_NotForbid(t *testing.T) {
@@ -418,11 +421,13 @@ func Test_Files_NotForbid(t *testing.T) {
t.Errorf("serve error: %v", err)
}
}()
- time.Sleep(time.Millisecond * 100)
- defer c.Stop()
+
+ time.Sleep(time.Second)
b, _, _ := get("http://localhost:6029/client.php")
assert.Equal(t, all("../../tests/client.php"), b)
+ assert.Equal(t, all("../../tests/client.php"), b)
+ c.Stop()
}
func tmpDir() string {
diff --git a/socket_factory_test.go b/socket_factory_test.go
index 8beb3fc6..c15e720a 100644
--- a/socket_factory_test.go
+++ b/socket_factory_test.go
@@ -105,9 +105,9 @@ func Test_Tcp_Failboot(t *testing.T) {
ls, err := net.Listen("tcp", "localhost:9007")
if assert.NoError(t, err) {
defer func() {
- err := ls.Close()
- if err != nil {
- t.Errorf("error closing the listener: error %v", err)
+ err3 := ls.Close()
+ if err3 != nil {
+ t.Errorf("error closing the listener: error %v", err3)
}
}()
} else {
@@ -116,10 +116,10 @@ func Test_Tcp_Failboot(t *testing.T) {
cmd := exec.Command("php", "tests/failboot.php")
- w, err := NewSocketFactory(ls, time.Minute).SpawnWorker(cmd)
+ w, err2 := NewSocketFactory(ls, time.Minute).SpawnWorker(cmd)
assert.Nil(t, w)
- assert.Error(t, err)
- assert.Contains(t, err.Error(), "failboot")
+ assert.Error(t, err2)
+ assert.Contains(t, err2.Error(), "failboot")
}
func Test_Tcp_Timeout(t *testing.T) {
@@ -193,8 +193,9 @@ func Test_Tcp_Broken(t *testing.T) {
}()
defer func() {
- err = w.Stop()
- assert.Error(t, err)
+ time.Sleep(time.Second)
+ err2 := w.Stop()
+ assert.NoError(t, err2)
}()
res, err := w.Exec(&Payload{Body: []byte("hello")})
@@ -375,8 +376,9 @@ func Test_Unix_Broken(t *testing.T) {
}()
defer func() {
+ time.Sleep(time.Second)
err = w.Stop()
- assert.Error(t, err)
+ assert.NoError(t, err)
}()
res, err := w.Exec(&Payload{Body: []byte("hello")})
diff --git a/static_pool_test.go b/static_pool_test.go
index 1f185f58..46f0bed8 100644
--- a/static_pool_test.go
+++ b/static_pool_test.go
@@ -151,11 +151,10 @@ func Test_StaticPool_Broken_Replace(t *testing.T) {
cfg,
)
assert.NoError(t, err)
- defer p.Destroy()
-
assert.NotNil(t, p)
done := make(chan interface{})
+
p.Listen(func(e int, ctx interface{}) {
if err, ok := ctx.(error); ok {
if strings.Contains(err.Error(), "undefined_function()") {
@@ -170,8 +169,10 @@ func Test_StaticPool_Broken_Replace(t *testing.T) {
assert.Nil(t, res)
<-done
+ p.Destroy()
}
+
func Test_StaticPool_Broken_FromOutside(t *testing.T) {
p, err := NewPool(
func() *exec.Cmd { return exec.Command("php", "tests/client.php", "echo", "pipes") },
@@ -218,26 +219,33 @@ func Test_StaticPool_AllocateTimeout(t *testing.T) {
NewPipeFactory(),
Config{
NumWorkers: 1,
- AllocateTimeout: time.Millisecond * 50,
- DestroyTimeout: time.Second,
+ AllocateTimeout: time.Nanosecond * 1,
+ DestroyTimeout: time.Second * 2,
},
)
-
- assert.NotNil(t, p)
- assert.NoError(t, err)
+ if err != nil {
+ t.Fatal(err)
+ }
done := make(chan interface{})
go func() {
- _, err := p.Exec(&Payload{Body: []byte("100")})
- assert.NoError(t, err)
- close(done)
+ if p != nil {
+ _, err := p.Exec(&Payload{Body: []byte("100")})
+ assert.NoError(t, err)
+ close(done)
+ } else {
+ t.Fatal("Pool is nil")
+ }
}()
+
// to ensure that worker is already busy
time.Sleep(time.Millisecond * 10)
_, err = p.Exec(&Payload{Body: []byte("10")})
- assert.Error(t, err)
+ if err == nil {
+ t.Fatal("Test_StaticPool_AllocateTimeout exec should raise error")
+ }
assert.Contains(t, err.Error(), "worker timeout")
<-done
diff --git a/util/network.go b/util/network.go
index b9066de7..d858cb0a 100644
--- a/util/network.go
+++ b/util/network.go
@@ -1,8 +1,11 @@
+// +build linux darwin freebsd
+
package util
import (
"errors"
"fmt"
+ "github.com/valyala/tcplisten"
"net"
"os"
"strings"
@@ -27,6 +30,18 @@ func CreateListener(address string) (net.Listener, error) {
}
}
+ cfg := tcplisten.Config{
+ ReusePort: true,
+ DeferAccept: true,
+ FastOpen: true,
+ Backlog: 0,
+ }
+
+ // tcp4 is currently supported
+ if dsn[0] == "tcp" {
+ return cfg.NewListener("tcp4", dsn[1])
+ }
+
return net.Listen(dsn[0], dsn[1])
}
diff --git a/util/network_test.go b/util/network_test.go
index 830e1b8a..09157ec0 100644
--- a/util/network_test.go
+++ b/util/network_test.go
@@ -1,8 +1,9 @@
+// +build linux darwin freebsd
+
package util
import (
"github.com/stretchr/testify/assert"
- "runtime"
"testing"
)
@@ -15,10 +16,6 @@ func TestCreateListener(t *testing.T) {
}
func TestUnixCreateListener(t *testing.T) {
- if runtime.GOOS == "windows" {
- t.Skip("not supported on " + runtime.GOOS)
- }
-
l, err := CreateListener("unix://file.sock")
assert.NoError(t, err)
l.Close()
diff --git a/util/network_windows.go b/util/network_windows.go
new file mode 100644
index 00000000..e5bc67c8
--- /dev/null
+++ b/util/network_windows.go
@@ -0,0 +1,33 @@
+// +build windows
+
+package util
+
+import (
+ "errors"
+ "fmt"
+ "net"
+ "os"
+ "strings"
+ "syscall"
+)
+
+// CreateListener crates socket listener based on DSN definition.
+func CreateListener(address string) (net.Listener, error) {
+ dsn := strings.Split(address, "://")
+ if len(dsn) != 2 {
+ return nil, errors.New("invalid DSN (tcp://:6001, unix://file.sock)")
+ }
+
+ if dsn[0] != "unix" && dsn[0] != "tcp" {
+ return nil, errors.New("invalid Protocol (tcp://:6001, unix://file.sock)")
+ }
+
+ if dsn[0] == "unix" && fileExists(dsn[1]) {
+ err := syscall.Unlink(dsn[1])
+ if err != nil {
+ return nil, fmt.Errorf("error during the unlink syscall: error %v", err)
+ }
+ }
+
+ return net.Listen(dsn[0], dsn[1])
+} \ No newline at end of file
diff --git a/util/network_windows_test.go b/util/network_windows_test.go
new file mode 100644
index 00000000..a5a8064e
--- /dev/null
+++ b/util/network_windows_test.go
@@ -0,0 +1,16 @@
+// +build windows
+
+package util
+
+import (
+ "github.com/stretchr/testify/assert"
+ "testing"
+)
+
+func TestCreateListener(t *testing.T) {
+ _, err := CreateListener("unexpected dsn")
+ assert.Error(t, err, "Invalid DSN (tcp://:6001, unix://file.sock)")
+
+ _, err = CreateListener("aaa://192.168.0.1")
+ assert.Error(t, err, "Invalid Protocol (tcp://:6001, unix://file.sock)")
+} \ No newline at end of file
diff --git a/worker_test.go b/worker_test.go
index e8cbef90..c21e67cb 100644
--- a/worker_test.go
+++ b/worker_test.go
@@ -4,6 +4,7 @@ import (
"github.com/stretchr/testify/assert"
"os/exec"
"testing"
+ "time"
)
func Test_GetState(t *testing.T) {
@@ -160,21 +161,23 @@ func Test_Echo_Slow(t *testing.T) {
func Test_Broken(t *testing.T) {
cmd := exec.Command("php", "tests/client.php", "broken", "pipes")
- w, _ := NewPipeFactory().SpawnWorker(cmd)
+ w, err := NewPipeFactory().SpawnWorker(cmd)
+ if err != nil {
+ t.Fatal(err)
+ }
+
go func() {
err := w.Wait()
assert.Error(t, err)
assert.Contains(t, err.Error(), "undefined_function()")
}()
- defer func() {
- err := w.Stop()
- assert.Error(t, err)
- }()
-
res, err := w.Exec(&Payload{Body: []byte("hello")})
assert.Nil(t, res)
assert.NotNil(t, err)
+
+ time.Sleep(time.Second)
+ assert.NoError(t, w.Stop())
}
func Test_OnStarted(t *testing.T) {