Experiments to improve the testability of warden.
These objectives are those of the original guardian project and should not be confused with the objectives of the later project, also dubbed "guardian", to re-implement the container support of garden-linux on runc.
- Understandability: the code should be clearly structured and documented so that a newcomer can understand the rationale and be able to propose changes.
- Robustness: the code should function correctly or fail with meaningful diagnostics.
- Maintainability: it should be straightforward to fix bugs and add new features.
- Testability: the runtime code should be thoroughly exercised by the tests.
- Portability: it should be straightforward to port the code to other Linux distributions.
These objectives will be achieved through the following practices:
- Construct separately testable components with documented interfaces.
- Test each component including error paths.
- Keep runtime and test code separate.
- Fail rather than degrade function.
- Operating system dependencies should be isolated and carefully managed to simplify porting.
- Use pure Go for maintainability. Avoid scripting (even in Go) and C code.
- Instrument code to capture failure diagnostics including error identifiers (described below) and stack traces.
Documentation is available at godoc.org.
If this hasn't been refreshed for a while, feel free to click the "Refresh now" link.
Errors returned from Guardian functions and methods include error identifiers to uniquely identify each kind of failure and stack traces so that the point of failure can easily be determined. The gerror package is used to construct errors.
Logging is performed using the glog package (an external dependency).
glog
has four logging levels: informational (glog.Info()
), warning (glog.Warning()
), error (glog.Error()
), and fatal (glog.Fatal()
). Additionally, glog
has a verbosity level which is a non-negative integer with a default value of 0
. Guardian uses informational logs with verbosity level 0
to log important events and informational logs with verbosity levels 1
and higher for debugging.
Logs may be directed to standard error by setting the flag logtostderr
to true
on the go invocation, as in this example:
go test -logtostderr=true -vmodule=*=2
Note: the glog -v
flag clashes with the boolean -v
flag of go test
and so the logging verbosity should be set during testing using -vmodule=*=
.
See the glog documentation for further information.
The directories in this repository consist mostly of runtime code, tests (*_test.go
), and examples (*example*.go
). Directories named mock_*
contain mock implementations of interfaces for use in testing.
In addition, the development
directory contains scripts used during development and the test_support
directory contains shared functions and custom matchers used by tests.
-
Ensure the following pre-requisites are installed:
-
Create a Go workspace directory, such as
$HOME/go
, and add the path of this directory to the beginning of a new environment variable calledGOPATH
. You might want to put this last step in your profile.$ mkdir $HOME/go $ export GOPATH=$HOME/go
-
Get this repository into your workspace (
src
directory) by issuing:$ go get github.com/cf-guardian/guardian
-
Change directory to
<workspace dir>/src/github.com/cf-guardian/guardian
. -
Install the pre-commit hook as follows:
cd .git/hooks ln -s ../../development/pre-commit-hook/pre-commit .
After installing the hook, if you need to skip reformatting for a particular commit, use
git commit --no-verify
.
The directory development/scripts
is there for simple (bash) shell scripts that may make life a little easier in our context:
-
gosub
is designed to run ago
command in all subdirectories of the current directory that have a*.go
file in them. Typical usage isgosub build
, orgosub fmt build
. This saves being driven by a top-levelgo
package with explicit dependencies.gosub
is limited to single word go commands.gosub fmt build
would issuego fmt; go build
in each directory in turn.gosub test
is quite useful to run all tests in immediate subdirectories. -
govet
runsgo tool vet
with appropriate options against a single directory passed as a parameter to the script.
To run the tests in a specific directory, issue:
go test
If the tests succeed, this should print PASS
.
gomock
Unit testing is performed on packages. gomock is used as a mocking framework and to generate mock implementations of interfaces and thereby enable packages to be tested in isolation from each other.
Mocks are stored in a subdirectory of the directory containing the mocked interface. For example, the mocks for the kernel/fileutils
package are stored in kernel/fileutils/mock_fileutils
.
To re-generate the generated mock implementations of interfaces, ensure mockgen
is on the path and then run the script development/scripts/update_mocks
. If you add a generated mock, don't forget to add it to update_mocks
.
If your favourite text editor is not sufficient, try Eclipse with the goclipse plugin or IntelliJ IDEA with the go plugin.
Source code is formatted according to standard Go conventions. To re-format the code, issue:
go fmt ./...
To reformat code before committing it to git, install the pre-commit hook as described above.
Also, you can run go vet
(a govet
script is provided in development/scripts
) and lint against the code if you like.
Pull requests are welcome; see the contributor guidelines for details.
This buildpack is released under version 2.0 of the Apache License. See the LICENSE
file.