Skip to content

Commit

Permalink
#58 Coverage improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
docktermj committed Jul 9, 2024
1 parent 3a431d1 commit ba47bb5
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 97 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@
go.work
.history
target
coverage.html

66 changes: 65 additions & 1 deletion cmd/cmd_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,76 @@
package cmd

import (
"bytes"
"os"
"testing"

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

// ----------------------------------------------------------------------------
// Test public functions
// ----------------------------------------------------------------------------

/*
* The unit tests in this file simulate command line invocation.
*/
func TestMain(test *testing.T) {
func Test_Execute(test *testing.T) {
_ = test
os.Args = []string{"command-name", "--avoid-serving", "--tty-only"}
Execute()
}

func Test_Execute_completion(test *testing.T) {
_ = test
os.Args = []string{"command-name", "completion"}
Execute()
}

func Test_Execute_docs(test *testing.T) {
_ = test
os.Args = []string{"command-name", "docs"}
Execute()
}

func Test_Execute_help(test *testing.T) {
_ = test
os.Args = []string{"command-name", "--help"}
Execute()
}

func Test_PreRun(test *testing.T) {
_ = test
args := []string{"command-name", "--help"}
PreRun(RootCmd, args)
}

func Test_RunE(test *testing.T) {
test.Setenv("SENZING_TOOLS_AVOID_SERVING", "true")
err := RunE(RootCmd, []string{})
require.NoError(test, err)
}

func Test_RunE_badGrpcURL(test *testing.T) {
test.Setenv("SENZING_TOOLS_AVOID_SERVING", "true")
test.Setenv("SENZING_TOOLS_GRPC_URL", "grpc://bad")
err := RunE(RootCmd, []string{})
require.NoError(test, err)
}

// ----------------------------------------------------------------------------
// Test private functions
// ----------------------------------------------------------------------------

func Test_completionAction(test *testing.T) {
var buffer bytes.Buffer
err := completionAction(&buffer)
require.NoError(test, err)
}

func Test_docsAction_badDir(test *testing.T) {
var buffer bytes.Buffer
badDir := "/tmp/no/directory/exists"
err := docsAction(&buffer, badDir)
require.Error(test, err)
}
12 changes: 12 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/senzing-garage/demo-quickstart/httpserver"
"github.com/senzing-garage/go-cmdhelping/cmdhelper"
"github.com/senzing-garage/go-cmdhelping/option"
"github.com/senzing-garage/go-cmdhelping/option/optiontype"
"github.com/senzing-garage/go-cmdhelping/settings"
"github.com/senzing-garage/go-observing/observer"
"github.com/senzing-garage/go-rest-api-service/senzingrestservice"
Expand All @@ -33,11 +34,20 @@ A server supporting the following services:
`
)

var avoidServe = option.ContextVariable{
Arg: "avoid-serving",
Default: option.OsLookupEnvBool("SENZING_TOOLS_AVOID_SERVING", false),
Envar: "SENZING_TOOLS_AVOID_SERVING",
Help: "Avoid serving. For testing only. [%s]",
Type: optiontype.Bool,
}

// ----------------------------------------------------------------------------
// Context variables
// ----------------------------------------------------------------------------

var ContextVariablesForMultiPlatform = []option.ContextVariable{
avoidServe,
option.Configuration,
option.DatabaseURL,
option.EngineConfigurationJSON,
Expand Down Expand Up @@ -141,6 +151,7 @@ func RunE(_ *cobra.Command, _ []string) error {
// Setup gRPC server

grpcserver := &grpcserver.BasicGrpcServer{
AvoidServing: viper.GetBool(avoidServe.Arg),
EnableAll: true,
LogLevelName: viper.GetString(option.LogLevel.Arg),
ObserverOrigin: viper.GetString(option.ObserverOrigin.Arg),
Expand All @@ -155,6 +166,7 @@ func RunE(_ *cobra.Command, _ []string) error {

httpServer := &httpserver.BasicHTTPServer{
APIUrlRoutePrefix: "api",
AvoidServing: viper.GetBool(avoidServe.Arg),
EnableAll: true,
EntitySearchRoutePrefix: "entity-search",
LogLevelName: viper.GetString(option.LogLevel.Arg),
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ require (
github.com/senzing-garage/serve-grpc v0.7.4
github.com/spf13/cobra v1.8.1
github.com/spf13/viper v1.19.0
github.com/stretchr/testify v1.9.0
google.golang.org/grpc v1.65.0
)

Expand All @@ -24,6 +25,7 @@ require (
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/creack/pty v1.1.21 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dlclark/regexp2 v1.11.1 // indirect
github.com/fatih/color v1.17.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
Expand All @@ -44,6 +46,7 @@ require (
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/ogen-go/ogen v1.2.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.19.1 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.55.0 // indirect
Expand Down
196 changes: 100 additions & 96 deletions httpserver/httpserver_basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
// BasicHTTPServer is the default implementation of the HttpServer interface.
type BasicHTTPServer struct {
APIUrlRoutePrefix string // FIXME: Only works with "api"
AvoidServing bool
EnableAll bool
EnableEntitySearch bool
EnableSenzingRestAPI bool
Expand Down Expand Up @@ -80,6 +81,105 @@ type TemplateVariables struct {
//go:embed static/*
var static embed.FS

// ----------------------------------------------------------------------------
// Interface methods
// ----------------------------------------------------------------------------

/*
The Serve method simply prints the 'Something' value in the type-struct.
Input
- ctx: A context to control lifecycle.
Output
- Nothing is returned, except for an error. However, something is printed.
See the example output.
*/

func (httpServer *BasicHTTPServer) Serve(ctx context.Context) error {
rootMux := http.NewServeMux()
var userMessage string

// Enable Senzing HTTP REST API.

if httpServer.EnableAll || httpServer.EnableSenzingRestAPI {
senzingAPIMux := httpServer.getSenzingRestAPIMux(ctx)
rootMux.Handle(fmt.Sprintf("/%s/", httpServer.APIUrlRoutePrefix), http.StripPrefix("/api", senzingAPIMux))
userMessage = fmt.Sprintf("%sServing Senzing REST API at http://localhost:%d/%s\n", userMessage, httpServer.ServerPort, httpServer.APIUrlRoutePrefix)
}

// Enable Senzing HTTP REST API as reverse proxy.

if httpServer.EnableAll || httpServer.EnableSenzingRestAPI || httpServer.EnableEntitySearch {
senzingAPIProxyMux := httpServer.getSenzingRestAPIProxyMux(ctx)
rootMux.Handle("/entity-search/api/", http.StripPrefix("/entity-search/api", senzingAPIProxyMux))
userMessage = fmt.Sprintf("%sServing Senzing REST API Reverse Proxy at http://localhost:%d/%s\n", userMessage, httpServer.ServerPort, "entity-search/api")
}

// Enable Senzing Entity Search.

if httpServer.EnableAll || httpServer.EnableEntitySearch {
entitySearchMux := httpServer.getEntitySearchMux(ctx)
rootMux.Handle(fmt.Sprintf("/%s/", httpServer.EntitySearchRoutePrefix), http.StripPrefix("/entity-search", entitySearchMux))
userMessage = fmt.Sprintf("%sServing Entity Search at http://localhost:%d/%s\n", userMessage, httpServer.ServerPort, httpServer.EntitySearchRoutePrefix)
}

// Enable SwaggerUI.

if httpServer.EnableAll || httpServer.EnableSwaggerUI {
swaggerUIMux := httpServer.getSwaggerUIMux(ctx)
rootMux.Handle(fmt.Sprintf("/%s/", httpServer.SwaggerURLRoutePrefix), http.StripPrefix("/swagger", swaggerUIMux))
userMessage = fmt.Sprintf("%sServing SwaggerUI at http://localhost:%d/%s\n", userMessage, httpServer.ServerPort, httpServer.SwaggerURLRoutePrefix)
}

// Enable Xterm.

if httpServer.EnableAll || httpServer.EnableXterm {
err := os.Setenv("SENZING_ENGINE_CONFIGURATION_JSON", httpServer.SenzingSettings)
if err != nil {
panic(err)
}
xtermMux := httpServer.getXtermMux(ctx)
rootMux.Handle(fmt.Sprintf("/%s/", httpServer.XtermURLRoutePrefix), http.StripPrefix("/xterm", xtermMux))
userMessage = fmt.Sprintf("%sServing XTerm at http://localhost:%d/%s\n", userMessage, httpServer.ServerPort, httpServer.XtermURLRoutePrefix)
}

// Add route to template pages.

rootMux.HandleFunc("/site/", httpServer.siteFunc)
userMessage = fmt.Sprintf("%sServing Console at http://localhost:%d\n", userMessage, httpServer.ServerPort)

// Add route to static files.

rootDir, err := fs.Sub(static, "static/root")
if err != nil {
panic(err)
}
rootMux.Handle("/", http.StripPrefix("/", http.FileServer(http.FS(rootDir))))

// Start service.

listenOnAddress := fmt.Sprintf("%s:%v", httpServer.ServerAddress, httpServer.ServerPort)
userMessage = fmt.Sprintf("%sStarting server on interface:port '%s'...\n", userMessage, listenOnAddress)
fmt.Println(userMessage)
server := http.Server{
ReadHeaderTimeout: httpServer.ReadHeaderTimeout,
Addr: listenOnAddress,
Handler: rootMux,
}

// Start a web browser. Unless disabled.

if !httpServer.TtyOnly {
_ = browser.OpenURL(fmt.Sprintf("http://localhost:%d", httpServer.ServerPort))
}

if !httpServer.AvoidServing {
err = server.ListenAndServe()
}
return err
}

// ----------------------------------------------------------------------------
// Internal methods
// ----------------------------------------------------------------------------
Expand Down Expand Up @@ -246,99 +346,3 @@ func (httpServer *BasicHTTPServer) siteFunc(w http.ResponseWriter, r *http.Reque
filePath := fmt.Sprintf("static/templates%s", r.RequestURI)
httpServer.populateStaticTemplate(w, r, filePath, templateVariables)
}

// ----------------------------------------------------------------------------
// Interface methods
// ----------------------------------------------------------------------------

/*
The Serve method simply prints the 'Something' value in the type-struct.
Input
- ctx: A context to control lifecycle.
Output
- Nothing is returned, except for an error. However, something is printed.
See the example output.
*/

func (httpServer *BasicHTTPServer) Serve(ctx context.Context) error {
rootMux := http.NewServeMux()
var userMessage string

// Enable Senzing HTTP REST API.

if httpServer.EnableAll || httpServer.EnableSenzingRestAPI {
senzingAPIMux := httpServer.getSenzingRestAPIMux(ctx)
rootMux.Handle(fmt.Sprintf("/%s/", httpServer.APIUrlRoutePrefix), http.StripPrefix("/api", senzingAPIMux))
userMessage = fmt.Sprintf("%sServing Senzing REST API at http://localhost:%d/%s\n", userMessage, httpServer.ServerPort, httpServer.APIUrlRoutePrefix)
}

// Enable Senzing HTTP REST API as reverse proxy.

if httpServer.EnableAll || httpServer.EnableSenzingRestAPI || httpServer.EnableEntitySearch {
senzingAPIProxyMux := httpServer.getSenzingRestAPIProxyMux(ctx)
rootMux.Handle("/entity-search/api/", http.StripPrefix("/entity-search/api", senzingAPIProxyMux))
userMessage = fmt.Sprintf("%sServing Senzing REST API Reverse Proxy at http://localhost:%d/%s\n", userMessage, httpServer.ServerPort, "entity-search/api")
}

// Enable Senzing Entity Search.

if httpServer.EnableAll || httpServer.EnableEntitySearch {
entitySearchMux := httpServer.getEntitySearchMux(ctx)
rootMux.Handle(fmt.Sprintf("/%s/", httpServer.EntitySearchRoutePrefix), http.StripPrefix("/entity-search", entitySearchMux))
userMessage = fmt.Sprintf("%sServing Entity Search at http://localhost:%d/%s\n", userMessage, httpServer.ServerPort, httpServer.EntitySearchRoutePrefix)
}

// Enable SwaggerUI.

if httpServer.EnableAll || httpServer.EnableSwaggerUI {
swaggerUIMux := httpServer.getSwaggerUIMux(ctx)
rootMux.Handle(fmt.Sprintf("/%s/", httpServer.SwaggerURLRoutePrefix), http.StripPrefix("/swagger", swaggerUIMux))
userMessage = fmt.Sprintf("%sServing SwaggerUI at http://localhost:%d/%s\n", userMessage, httpServer.ServerPort, httpServer.SwaggerURLRoutePrefix)
}

// Enable Xterm.

if httpServer.EnableAll || httpServer.EnableXterm {
err := os.Setenv("SENZING_ENGINE_CONFIGURATION_JSON", httpServer.SenzingSettings)
if err != nil {
panic(err)
}
xtermMux := httpServer.getXtermMux(ctx)
rootMux.Handle(fmt.Sprintf("/%s/", httpServer.XtermURLRoutePrefix), http.StripPrefix("/xterm", xtermMux))
userMessage = fmt.Sprintf("%sServing XTerm at http://localhost:%d/%s\n", userMessage, httpServer.ServerPort, httpServer.XtermURLRoutePrefix)
}

// Add route to template pages.

rootMux.HandleFunc("/site/", httpServer.siteFunc)
userMessage = fmt.Sprintf("%sServing Console at http://localhost:%d\n", userMessage, httpServer.ServerPort)

// Add route to static files.

rootDir, err := fs.Sub(static, "static/root")
if err != nil {
panic(err)
}
rootMux.Handle("/", http.StripPrefix("/", http.FileServer(http.FS(rootDir))))

// Start service.

listenOnAddress := fmt.Sprintf("%s:%v", httpServer.ServerAddress, httpServer.ServerPort)
userMessage = fmt.Sprintf("%sStarting server on interface:port '%s'...\n", userMessage, listenOnAddress)
fmt.Println(userMessage)
server := http.Server{
ReadHeaderTimeout: httpServer.ReadHeaderTimeout,
Addr: listenOnAddress,
Handler: rootMux,
}

// Start a web browser. Unless disabled.

if !httpServer.TtyOnly {
_ = browser.OpenURL(fmt.Sprintf("http://localhost:%d", httpServer.ServerPort))
}

return server.ListenAndServe()
}
Binary file modified testdata/sqlite/G2C.db
Binary file not shown.

0 comments on commit ba47bb5

Please sign in to comment.