Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic integration test infrastructure (and new endpoint /api/v1/version for testing it) #741

Merged
merged 65 commits into from
Mar 6, 2017
Merged
Show file tree
Hide file tree
Changes from 59 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
5a73043
Implement '/api/v1/version'
typeless Jan 18, 2017
447b802
Cleanup and various fixes
typeless Jan 19, 2017
6ab4622
Enhance run.sh
typeless Jan 24, 2017
1f41c0b
Add install_test.go
typeless Jan 24, 2017
4e41eb1
Add parameter utils.Config for testing handlers
typeless Jan 24, 2017
8ab6fb9
Re-organize TestVersion.go
typeless Jan 24, 2017
1f7a314
Rename functions
typeless Jan 24, 2017
fcf470c
handling process cleanup properly
typeless Jan 24, 2017
86f12e1
Fix missing function renaming
typeless Jan 24, 2017
8a98268
Cleanup the 'retry' logic
typeless Jan 24, 2017
56c9278
Cleanup
typeless Jan 24, 2017
a62c847
Remove unneeded logging code
typeless Jan 24, 2017
1137e7a
Logging messages tweaking
typeless Jan 24, 2017
f8775f8
Logging message tweaking
typeless Jan 24, 2017
a5f9e7d
Fix logging messages
typeless Jan 24, 2017
6b8b09a
Use 'const' instead of hardwired numbers
typeless Jan 24, 2017
b603a31
We don't really need retries anymore
typeless Jan 24, 2017
19a0b63
Move constant ServerHttpPort to install_test.go
typeless Jan 24, 2017
5a85dd9
Restore mistakenly removed constant
typeless Jan 24, 2017
4b033b4
Add required comments to make the linter happy.
typeless Jan 24, 2017
78a697f
Fix comments and naming to address linter's complaints
typeless Jan 24, 2017
cec3dee
Detect Gitea executale version automatically
typeless Jan 24, 2017
37591d6
Remove tests/run.sh, `go test` suffices.
typeless Jan 24, 2017
c223dbd
Make `make build` a prerequisite of `make test`
typeless Jan 24, 2017
335b41f
Do not sleep before trying
typeless Jan 24, 2017
7f4e3f4
Speedup the server pinging loop
typeless Jan 24, 2017
b0686ee
Use defined const instead of hardwired numbers
typeless Jan 24, 2017
33a7561
Remove redundant error handling
typeless Jan 24, 2017
43d973d
Use a dedicated target for running code.gitea.io/tests
typeless Jan 26, 2017
235fa4b
Do not make 'test' depend on 'build' target
typeless Jan 26, 2017
662833f
Rectify the excluded package list
typeless Jan 26, 2017
9bcb255
Remove redundant 'exit 1'
typeless Jan 26, 2017
130e725
Change the API to allow passing test.T to test handlers
typeless Jan 29, 2017
4a2d00c
Make testing.T an embedded field
typeless Jan 29, 2017
c4343c0
Use assert.Equal to comparing results
typeless Jan 29, 2017
240e25b
Add copyright info
typeless Feb 1, 2017
ae80af3
Parametrized logging output
typeless Feb 1, 2017
06c1193
Use tmpdir instead
typeless Feb 1, 2017
0a6356f
Eliminate redundant casting
typeless Feb 1, 2017
0e161f8
Remove unneeded variable
typeless Feb 1, 2017
a30aff4
Fix last commit
typeless Feb 1, 2017
57fc992
Add missing copyright info
typeless Feb 1, 2017
fda4cca
Replace fmt.Fprintf with fmt.Fprint
typeless Feb 1, 2017
ae0dfd5
rename the xtest to integration-test
typeless Feb 7, 2017
856a854
Use Symlink instead of hard-link for cross-device linking
typeless Feb 21, 2017
a7a98fd
Turn debugging logs on
typeless Feb 21, 2017
7e1990b
Follow the existing framework for APIs
typeless Feb 21, 2017
0ef4b44
Output logs only if test.v is true
typeless Feb 21, 2017
b4ef83b
Re-order import statements
typeless Feb 22, 2017
f4bbd25
Enhance the error message
typeless Feb 23, 2017
83a4697
Fix comment which breaks the linter's rule
typeless Feb 23, 2017
a81ef4c
Rename 'integration-test' to 'e2e-test' for saving keystrokes
typeless Feb 23, 2017
6a60048
Add comment to avoid possible confusion
typeless Feb 23, 2017
175267d
Rename tests -> integration-tests
typeless Feb 23, 2017
2532c60
Use tests/integration for now
typeless Feb 23, 2017
3430d3a
tests/integration -> integrations
typeless Feb 24, 2017
6dedc14
Update Makefile accordingly
typeless Feb 24, 2017
e4ad394
Fix a missing change in Makefile
typeless Feb 24, 2017
b022db5
govendor update code.gitea.io/sdk/gitea
typeless Mar 4, 2017
7fe9959
Fix comment of struct fields
typeless Mar 5, 2017
a7547bf
Fix conditional nonsense
typeless Mar 5, 2017
01a2a73
Fix missing updates regarding version string changes
typeless Mar 5, 2017
55e54c3
Make variable naming more consistent
typeless Mar 5, 2017
22a7ad4
Check http status code
typeless Mar 5, 2017
3223af5
Rectify error messages
typeless Mar 5, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ JAVASCRIPTS :=
LDFLAGS := -X "main.Version=$(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//')" -X "main.Tags=$(TAGS)"

TARGETS ?= linux/*,darwin/*,windows/*
PACKAGES ?= $(shell go list ./... | grep -v /vendor/)
PACKAGES ?= $(filter-out code.gitea.io/gitea/integrations,$(shell go list ./... | grep -v /vendor/))
SOURCES ?= $(shell find . -name "*.go" -type f)

TAGS ?=
Expand Down Expand Up @@ -66,6 +66,11 @@ lint:
fi
for PKG in $(PACKAGES); do golint -set_exit_status $$PKG || exit 1; done;

.PHONY: integrations
integrations: TAGS=bindata sqlite
integrations: build
go test code.gitea.io/gitea/integrations

.PHONY: test
test:
for PKG in $(PACKAGES); do go test -cover -coverprofile $$GOPATH/src/$$PKG/coverage.out $$PKG || exit 1; done;
Expand Down
94 changes: 94 additions & 0 deletions integrations/install_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package integration

import (
"fmt"
"net/http"
"os"
"os/user"
"path/filepath"
"testing"
"time"

"code.gitea.io/gitea/integrations/internal/utils"
)

// The HTTP port listened by the Gitea server.
const ServerHTTPPort = "3001"

const _RetryLimit = 10

func makeSimpleSettings(user, workdir, port string) map[string][]string {
return map[string][]string{
"db_type": {"SQLite3"},
"db_host": {"localhost"},
"db_path": {workdir + "data/gitea.db"},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But the test db data will stay with production data?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 'workdir' is created by ioutil.TempDir if not specified (that is, an empty string).

My comment regarding the field WorkDir is outdated and does not match with the reality. I'll fix it. Thanks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

"app_name": {"Gitea: Git with a cup of tea"},
"repo_root_path": {workdir + "repositories"},
"run_user": {user},
"domain": {"localhost"},
"ssh_port": {"22"},
"http_port": {port},
"app_url": {"http://localhost:" + port},
"log_root_path": {workdir + "log"},
}
}

func install(t *utils.T) error {
var r *http.Response
var err error

for i := 1; i <= _RetryLimit; i++ {

r, err = http.Get("http://:" + ServerHTTPPort + "/")
if err == nil {
fmt.Fprintln(os.Stderr)
break
}

// Give the server some amount of time to warm up.
time.Sleep(100 * time.Millisecond)
fmt.Fprint(os.Stderr, ".")
}

if err != nil {
return err
}

defer r.Body.Close()

_user, err := user.Current()
if err != nil {
return err
}

path, err := filepath.Abs(t.Config.WorkDir)
if err != nil {
return err
}

settings := makeSimpleSettings(_user.Username, path, ServerHTTPPort)
resp, err := http.PostForm("http://:"+ServerHTTPPort+"/install", settings)
if err != nil {
return err
}
defer resp.Body.Close()

return nil
}

func TestInstall(t *testing.T) {
conf := utils.Config{
Program: "../gitea",
WorkDir: "",
Args: []string{"web", "--port", ServerHTTPPort},
LogFile: os.Stderr,
}

if err := utils.New(t, &conf).RunTest(install); err != nil {
t.Fatal(err)
}
}
125 changes: 125 additions & 0 deletions integrations/internal/utils/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package utils

import (
"errors"
"io"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
"syscall"
"testing"
)

// T wraps testing.T and the configurations of the testing instance.
type T struct {
*testing.T
Config *Config
}

// New create an instance of T
func New(t *testing.T, c *Config) *T {
return &T{T: t, Config: c}
}

// Config Settings of the testing program
type Config struct {
// The executable path of the tested program.
Program string
// Working directory prepared for the tested program.
// If empty, a directory named with random suffixes is picked, and created under the current directory.
// The directory will be removed when the test finishes.
WorkDir string
// Command-line arguments passed to the tested program.
Args []string

// Where to redirect the stdout/stderr to. For debugging purposes.
LogFile *os.File
}

func redirect(cmd *exec.Cmd, f *os.File) error {
stdout, err := cmd.StdoutPipe()
if err != nil {
return err
}

stderr, err := cmd.StderrPipe()
if err != nil {
return err
}

go io.Copy(f, stdout)
go io.Copy(f, stderr)
return nil
}

// RunTest Helper function for setting up a running Gitea server for functional testing and then gracefully terminating it.
func (t *T) RunTest(tests ...func(*T) error) (err error) {
if t.Config.Program == "" {
return errors.New("Need input file")
}

path, err := filepath.Abs(t.Config.Program)
if err != nil {
return err
}

workdir := t.Config.WorkDir
if workdir == "" {
workdir, err = ioutil.TempDir(os.TempDir(), "gitea_tests-")
if err != nil {
return err
}
defer os.RemoveAll(workdir)
}

newpath := filepath.Join(workdir, filepath.Base(path))
if err := os.Symlink(path, newpath); err != nil {
return err
}

log.Printf("Starting the server: %s args:%s workdir:%s", newpath, t.Config.Args, workdir)

cmd := exec.Command(newpath, t.Config.Args...)
cmd.Dir = workdir

if t.Config.LogFile != nil && testing.Verbose() {
if err := redirect(cmd, t.Config.LogFile); err != nil {
return err
}
}

if err := cmd.Start(); err != nil {
return err
}

log.Println("Server started.")

defer func() {
// Do not early return. We have to call Wait anyway.
_ = cmd.Process.Signal(syscall.SIGTERM)

if _err := cmd.Wait(); _err != nil {
if _err.Error() != "signal: terminated" {
err = _err
return
}
}

log.Println("Server exited")
}()

for _, fn := range tests {
if err := fn(t); err != nil {
return err
}
}

// Note that the return value 'err' may be updated by the 'defer' statement before despite it's returning nil here.
return nil
}
77 changes: 77 additions & 0 deletions integrations/version_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package integration

import (
"bytes"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"

"code.gitea.io/gitea/integrations/internal/utils"

"github.com/stretchr/testify/assert"
)

func version(t *utils.T) error {
var err error

path, err := filepath.Abs(t.Config.Program)
if err != nil {
return err
}

cmd := exec.Command(path, "--version")
out, err := cmd.Output()
if err != nil {
return err
}

fields := strings.Fields(string(out))
if len(fields) != 3 {
return fmt.Errorf("unexpected version string '%s'", out)
}

expected := fields[2]

var r *http.Response
r, err = http.Get("http://:" + ServerHTTPPort + "/api/v1/version")
if err == nil {
return err
}

defer r.Body.Close()

buf, err := ioutil.ReadAll(r.Body)
if err != nil {
return err
}

actual := string(bytes.TrimSpace(buf))

log.Printf("Actual: \"%s\" Expected: \"%s\"\n", actual, expected)
assert.Equal(t, expected, actual)

return nil
}

func TestVersion(t *testing.T) {
conf := utils.Config{
Program: "../gitea",
WorkDir: "",
Args: []string{"web", "--port", ServerHTTPPort},
LogFile: os.Stderr,
}

if err := utils.New(t, &conf).RunTest(install, version); err != nil {
t.Fatal(err)
}
}
1 change: 1 addition & 0 deletions routers/api/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ func RegisterRoutes(m *macaron.Macaron) {

m.Group("/v1", func() {
// Miscellaneous
m.Get("/version", misc.Version)
m.Post("/markdown", bind(api.MarkdownOption{}), misc.Markdown)
m.Post("/markdown/raw", misc.MarkdownRaw)

Expand Down
16 changes: 16 additions & 0 deletions routers/api/v1/misc/version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package misc
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to include copyright info

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. 069155d249b94bb89a84a27002db177c072672c1


import (
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/sdk/gitea"
)

// Version shows the version of the Gitea server
func Version(ctx *context.APIContext) {
ctx.JSON(200, &gitea.ServerVersion{Version: setting.AppVer})
}
11 changes: 11 additions & 0 deletions vendor/code.gitea.io/sdk/gitea/miscellaneous.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions vendor/vendor.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
"revisionTime": "2017-02-22T02:52:05Z"
},
{
"checksumSHA1": "K0VWBaa3ZUE598zVFGavdLB7vW4=",
"checksumSHA1": "qXD1HI8bTn7qNJZJOeZqQgxo354=",
"path": "code.gitea.io/sdk/gitea",
"revision": "06902fe19508c7ede2be38b71287c665efa1f10d",
"revisionTime": "2017-02-19T11:17:32Z"
"revision": "8807a1d2ced513880b288a5e2add39df6bf72144",
"revisionTime": "2017-03-04T10:22:44Z"
},
{
"checksumSHA1": "IyfS7Rbl6OgR83QR7TOfKdDCq+M=",
Expand Down