diff --git a/Dockerfile.tests b/Dockerfile.tests new file mode 100644 index 00000000..f2f1f2a7 --- /dev/null +++ b/Dockerfile.tests @@ -0,0 +1,32 @@ +FROM golang:1.10-stretch + +LABEL authors="Julien Neuhart " + +# |-------------------------------------------------------------------------- +# | Libraries +# |-------------------------------------------------------------------------- +# | +# | Installs all required libraries. +# | + +RUN echo "deb http://httpredir.debian.org/debian/ stretch main contrib non-free" > /etc/apt/sources.list &&\ + apt-get update &&\ + apt-get install -y xvfb wkhtmltopdf pdftk unoconv ttf-mscorefonts-installer &&\ + ln -s /usr/bin/xvfb-run /usr/local/bin/xvfb-run &&\ + ln -s /usr/bin/wkhtmltopdf /usr/local/bin/wkhtmltopdf &&\ + ln -s /usr/bin/pdftk /usr/local/bin/pdftk &&\ + ln -s /usr/bin/unoconv /usr/local/bin/unoconv + +# |-------------------------------------------------------------------------- +# | Gotenberg +# |-------------------------------------------------------------------------- +# | +# | All Gotenberg related stuff. +# | + +WORKDIR /go/src/github.com/gulien/gotenberg +COPY . . + +RUN go get -d -v ./... + +CMD ["go", "test", "-race", "-cover", "./..."] \ No newline at end of file diff --git a/_tests/configurations/broken-gotenberg.yml b/_tests/configurations/broken-gotenberg.yml new file mode 100644 index 00000000..01a20b71 --- /dev/null +++ b/_tests/configurations/broken-gotenberg.yml @@ -0,0 +1,17 @@ +port: 3000 +logs: + level: "DEBUG" + format: { + value: [ + ... + } +commands: + html: + timeout: 30 + template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}" + office: + timeout: 30 + template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\"" + merge: + timeout: 30 + template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}" diff --git a/_tests/configurations/gotenberg.yml b/_tests/configurations/gotenberg.yml new file mode 100644 index 00000000..87459cf2 --- /dev/null +++ b/_tests/configurations/gotenberg.yml @@ -0,0 +1,14 @@ +port: 3000 +logs: + level: "DEBUG" + format: "text" +commands: + html: + timeout: 30 + template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}" + office: + timeout: 30 + template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\"" + merge: + timeout: 30 + template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}" diff --git a/_tests/configurations/wrong-html-command-template-gotenberg.yml b/_tests/configurations/wrong-html-command-template-gotenberg.yml new file mode 100644 index 00000000..1ea42ca2 --- /dev/null +++ b/_tests/configurations/wrong-html-command-template-gotenberg.yml @@ -0,0 +1,14 @@ +port: 3000 +logs: + level: "DEBUG" + format: "text" +commands: + html: + timeout: 30 + template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ FilePath }} {{ .ResultFilePath }}" + office: + timeout: 30 + template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\"" + merge: + timeout: 30 + template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}" diff --git a/_tests/configurations/wrong-logging-format-gotenberg.yml b/_tests/configurations/wrong-logging-format-gotenberg.yml new file mode 100644 index 00000000..b627462f --- /dev/null +++ b/_tests/configurations/wrong-logging-format-gotenberg.yml @@ -0,0 +1,14 @@ +port: 3000 +logs: + level: "DEBUG" + format: "DEBUG" +commands: + html: + timeout: 30 + template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}" + office: + timeout: 30 + template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\"" + merge: + timeout: 30 + template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}" diff --git a/_tests/configurations/wrong-logging-level-gotenberg.yml b/_tests/configurations/wrong-logging-level-gotenberg.yml new file mode 100644 index 00000000..cab7bb49 --- /dev/null +++ b/_tests/configurations/wrong-logging-level-gotenberg.yml @@ -0,0 +1,14 @@ +port: 3000 +logs: + level: "text" + format: "text" +commands: + html: + timeout: 30 + template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}" + office: + timeout: 30 + template: "unoconv --format pdf --output \"{{ .ResultFilePath }}\" \"{{ .FilePath }}\"" + merge: + timeout: 30 + template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}" diff --git a/_tests/configurations/wrong-merge-command-template-gotenberg.yml b/_tests/configurations/wrong-merge-command-template-gotenberg.yml new file mode 100644 index 00000000..c0cad22a --- /dev/null +++ b/_tests/configurations/wrong-merge-command-template-gotenberg.yml @@ -0,0 +1,14 @@ +port: 3000 +logs: + level: "DEBUG" + format: "text" +commands: + html: + timeout: 30 + template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}" + office: + timeout: 30 + template: "unoconv --format pdf --output {{ .ResultFilePath }}\" \"{{ .FilePath }}\"" + merge: + timeout: 30 + template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} cat output {{ .ResultFilePath }}" diff --git a/_tests/configurations/wrong-office-command-template-gotenberg.yml b/_tests/configurations/wrong-office-command-template-gotenberg.yml new file mode 100644 index 00000000..a2aa6cc2 --- /dev/null +++ b/_tests/configurations/wrong-office-command-template-gotenberg.yml @@ -0,0 +1,14 @@ +port: 3000 +logs: + level: "DEBUG" + format: "text" +commands: + html: + timeout: 30 + template: "xvfb-run -e /dev/stdout wkhtmltopdf {{ .FilePath }} {{ .ResultFilePath }}" + office: + timeout: 30 + template: "unoconv --format pdf --output \"{{ ResultFilePath }}\" \"{{ .FilePath }}\"" + merge: + timeout: 30 + template: "pdftk {{ range $filePath := .FilesPaths }} {{ $filePath }} {{ end }} cat output {{ .ResultFilePath }}" diff --git a/app/app.go b/app/app.go index 2dc73be0..5260e708 100644 --- a/app/app.go +++ b/app/app.go @@ -26,8 +26,8 @@ type App struct { // NewApp instantiates the application by loading the configuration from the // gotenberg.yml file. -func NewApp(version string) (*App, error) { - c, err := config.NewAppConfig() +func NewApp(version string, configurationFilePath string) (*App, error) { + c, err := config.NewAppConfig(configurationFilePath) if err != nil { return nil, err } diff --git a/app/app_test.go b/app/app_test.go new file mode 100644 index 00000000..19fbdb18 --- /dev/null +++ b/app/app_test.go @@ -0,0 +1,30 @@ +package app + +import ( + "path/filepath" + "testing" +) + +func TestNewApp(t *testing.T) { + // case 1: uses an empty configuration file path. + if _, err := NewApp("tests", ""); err == nil { + t.Error("App should not have been instantiated!") + } + + // case 2: uses an correct configuration file. + path, _ := filepath.Abs("../_tests/configurations/gotenberg.yml") + if _, err := NewApp("tests", path); err != nil { + t.Error("App should have been instantiated!") + } +} + +func TestRun(t *testing.T) { + path, _ := filepath.Abs("../_tests/configurations/gotenberg.yml") + a, _ := NewApp("tests", path) + + quit := make(chan bool, 1) + go func() { + a.Run() + }() + quit <- true +} diff --git a/app/config/config.go b/app/config/config.go index 2b44ea6e..48fa1639 100644 --- a/app/config/config.go +++ b/app/config/config.go @@ -56,8 +56,8 @@ type ( // NewAppConfig instantiates the application's configuration. // If something bad happens here, the application should not start. -func NewAppConfig() (*AppConfig, error) { - fileConfig, err := loadFileConfig() +func NewAppConfig(configurationFilePath string) (*AppConfig, error) { + fileConfig, err := loadFileConfig(configurationFilePath) if err != nil { return nil, err } @@ -131,12 +131,9 @@ type fileConfig struct { } `yaml:"commands"` } -// configurationFilePath is our default configuration file to parse. -const configurationFilePath = "gotenberg.yml" - // loadFileConfig instantiates a fileConfig instance by loading // the configuration file gotenberg.yml. -func loadFileConfig() (*fileConfig, error) { +func loadFileConfig(configurationFilePath string) (*fileConfig, error) { c := &fileConfig{} data, err := ioutil.ReadFile(configurationFilePath) diff --git a/app/config/config_test.go b/app/config/config_test.go new file mode 100644 index 00000000..2e809a80 --- /dev/null +++ b/app/config/config_test.go @@ -0,0 +1,55 @@ +package config + +import ( + "path/filepath" + "testing" +) + +func TestNewAppConfig(t *testing.T) { + // case 1: uses an empty configuration file path. + if _, err := NewAppConfig(""); err == nil { + t.Error("AppConfig should not have been instantiated!") + } + + // case 2: uses a broken configuration file. + path, _ := filepath.Abs("../../_tests/configurations/broken-gotenberg.yml") + if _, err := NewAppConfig(path); err == nil { + t.Error("AppConfig should not have been instantiated!") + } + + // case 3: uses a configuration file with a wrong logging level. + path, _ = filepath.Abs("../../_tests/configurations/wrong-logging-level-gotenberg.yml") + if _, err := NewAppConfig(path); err == nil { + t.Error("AppConfig should not have been instantiated!") + } + + // case 4: uses a configuration file with a wrong logging format. + path, _ = filepath.Abs("../../_tests/configurations/wrong-logging-format-gotenberg.yml") + if _, err := NewAppConfig(path); err == nil { + t.Error("AppConfig should not have been instantiated!") + } + + // case 5: uses a configuration file with a wrong HTML command template. + path, _ = filepath.Abs("../../_tests/configurations/wrong-html-command-template-gotenberg.yml") + if _, err := NewAppConfig(path); err == nil { + t.Error("AppConfig should not have been instantiated!") + } + + // case 6: uses a configuration file with a wrong Office command template. + path, _ = filepath.Abs("../../_tests/configurations/wrong-office-command-template-gotenberg.yml") + if _, err := NewAppConfig(path); err == nil { + t.Error("AppConfig should not have been instantiated!") + } + + // case 7: uses a configuration file with a wrong merge command template. + path, _ = filepath.Abs("../../_tests/configurations/wrong-merge-command-template-gotenberg.yml") + if _, err := NewAppConfig(path); err == nil { + t.Error("AppConfig should not have been instantiated!") + } + + // case 8: uses a correct configuration file. + path, _ = filepath.Abs("../../_tests/configurations/gotenberg.yml") + if _, err := NewAppConfig(path); err != nil { + t.Error("AppConfig should have been instantiated!") + } +} diff --git a/main.go b/main.go index 35a8d1e3..cf0fe35c 100644 --- a/main.go +++ b/main.go @@ -22,10 +22,13 @@ import ( // version will be set on build time. var version = "master" +// defaultConfigurationFilePath is our default configuration file to parse. +const defaultConfigurationFilePath = "gotenberg.yml" + // main initializes the application, starts it, and handles // graceful shutdown. func main() { - a, err := app.NewApp(version) + a, err := app.NewApp(version, defaultConfigurationFilePath) if err != nil { logger.SetLevel(logrus.InfoLevel) logger.Fatal(err) diff --git a/orbit.yml b/orbit.yml index ece8a2e4..bcdb5b22 100644 --- a/orbit.yml +++ b/orbit.yml @@ -1,7 +1,7 @@ tasks: - use: install - short: Installs all required dependencies + short: Installs all required dev dependencies run: - go get -u github.com/golang/dep/cmd/dep - go get -u gopkg.in/alecthomas/gometalinter.v2 @@ -13,19 +13,19 @@ tasks: - go fmt ./... - gometalinter.v2 --disable-all -E vet -E gofmt -E misspell -E ineffassign -E goimports -E deadcode -E gocyclo --vendor ./... + - use: tests + short: Runs tests inside a container + run: + - docker build -t gotenberg:tests -f Dockerfile.tests . + - docker run --rm gotenberg:tests + - use: build short: Builds a Linux binary and the Docker image run: - env GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -ldflags "-X main.version={{ .Orbit.Version }}" - - docker build . -t gotenberg:snapshot + - docker build . -t gotenberg:{{ .Orbit.Version }} - use: up - short: Starts the snapshot version of the Gotenberg image + short: Starts the {{ .Orbit.Version }} version of the Gotenberg image run: - - docker run -p 3000:3000/tcp --name=gotenberg gotenberg:{{ .Orbit.Version }} - - - use: stop - short: Stops the snapshot version of the Gotenberg image - run : - - docker stop gotenberg - - docker rm gotenberg \ No newline at end of file + - docker run --rm -p 3000:3000/tcp --name=gotenberg gotenberg:{{ .Orbit.Version }} \ No newline at end of file