This repository has been archived by the owner on Nov 8, 2022. It is now read-only.
Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
snap/snapteld_test.go
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
409 lines (376 sloc)
10.8 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// +build small | |
/* | |
http://www.apache.org/licenses/LICENSE-2.0.txt | |
Copyright 2017 Intel Corporation | |
Licensed under the Apache License, Version 2.0 (the "License"); | |
you may not use this file except in compliance with the License. | |
You may obtain a copy of the License at | |
http://www.apache.org/licenses/LICENSE-2.0 | |
Unless required by applicable law or agreed to in writing, software | |
distributed under the License is distributed on an "AS IS" BASIS, | |
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
See the License for the specific language governing permissions and | |
limitations under the License. | |
*/ | |
package main | |
import ( | |
"encoding/json" | |
"strconv" | |
"testing" | |
"time" | |
. "github.com/smartystreets/goconvey/convey" | |
"github.com/vrischmann/jsonutil" | |
"github.com/intelsdi-x/snap/control" | |
"github.com/intelsdi-x/snap/mgmt/rest" | |
"github.com/intelsdi-x/snap/mgmt/tribe" | |
"github.com/intelsdi-x/snap/pkg/cfgfile" | |
"github.com/intelsdi-x/snap/scheduler" | |
) | |
var validCmdlineFlags_input = mockFlags{ | |
"max-procs": "11", | |
"log-level": "1", | |
"log-path": "/no/logs/allowed", | |
"log-truncate": "true", | |
"log-colors": "true", | |
"max-running-plugins": "12", | |
"plugin-load-timeout": "20", | |
"plugin-trust": "1", | |
"auto-discover": "/no/plugins/here", | |
"keyring-paths": "/no/keyrings/here", | |
"cache-expiration": "30ms", | |
"control-listen-addr": "100.101.102.103", | |
"control-listen-port": "10400", | |
"pprof": "true", | |
"temp_dir_path": "/no/temp/files", | |
"tls-cert": "/no/cert/here", | |
"tls-key": "/no/key/here", | |
"ca-cert-paths": "/no/root/certs", | |
"disable-api": "false", | |
"api-port": "12400", | |
"api-addr": "120.121.122.123", | |
"rest-https": "true", | |
"rest-cert": "/no/rest/cert", | |
"rest-key": "/no/rest/key", | |
"rest-auth": "true", | |
"rest-auth-pwd": "noway", | |
"allowed_origins": "140.141.142.143", | |
"work-manager-queue-size": "70", | |
"work-manager-pool-size": "71", | |
"tribe-node-name": "bonk", | |
"tribe": "true", | |
"tribe-addr": "160.161.162.163", | |
"tribe-port": "16400", | |
"tribe-seed": "180.181.182.183", | |
} | |
var validCmdlineFlags_expected = &Config{ | |
Control: &control.Config{ | |
MaxRunningPlugins: 12, | |
PluginLoadTimeout: 20, | |
PluginTrust: 1, | |
AutoDiscoverPath: "/no/plugins/here", | |
KeyringPaths: "/no/keyrings/here", | |
CacheExpiration: jsonutil.Duration{30 * time.Millisecond}, | |
ListenAddr: "100.101.102.103", | |
ListenPort: 10400, | |
Pprof: true, | |
TempDirPath: "/no/temp/files", | |
TLSCertPath: "/no/cert/here", | |
TLSKeyPath: "/no/key/here", | |
CACertPaths: "/no/root/certs", | |
}, | |
RestAPI: &rest.Config{ | |
Enable: true, | |
Port: 12400, | |
Address: "120.121.122.123:12400", | |
HTTPS: true, | |
RestCertificate: "/no/rest/cert", | |
RestKey: "/no/rest/key", | |
RestAuth: true, | |
RestAuthPassword: "noway", | |
Pprof: true, | |
Corsd: "140.141.142.143", | |
}, | |
Tribe: &tribe.Config{ | |
Name: "bonk", | |
Enable: true, | |
BindAddr: "160.161.162.163", | |
BindPort: 16400, | |
Seed: "180.181.182.183", | |
}, | |
Scheduler: &scheduler.Config{ | |
WorkManagerQueueSize: 70, | |
WorkManagerPoolSize: 71, | |
}, | |
GoMaxProcs: 11, | |
LogLevel: 1, | |
LogPath: "/no/logs/allowed", | |
LogTruncate: true, | |
LogColors: true, | |
} | |
func TestSnapConfig(t *testing.T) { | |
Convey("Test Config", t, func() { | |
Convey("with defaults", func() { | |
cfg := getDefaultConfig() | |
jb, _ := json.Marshal(cfg) | |
serrs := cfgfile.ValidateSchema(CONFIG_CONSTRAINTS, string(jb)) | |
So(len(serrs), ShouldEqual, 0) | |
}) | |
}) | |
} | |
func TestSnapConfigEmpty(t *testing.T) { | |
Convey("Test Config", t, func() { | |
Convey("with empty plugin config sections", func() { | |
cfg := getDefaultConfig() | |
readConfig(cfg, "./examples/configs/snap-config-empty.yaml") | |
jb, _ := json.Marshal(cfg) | |
serrs := cfgfile.ValidateSchema(CONFIG_CONSTRAINTS, string(jb)) | |
So(len(serrs), ShouldEqual, 0) | |
}) | |
}) | |
} | |
type mockFlags map[string]string | |
func (m mockFlags) String(key string) string { | |
return m[key] | |
} | |
func (m mockFlags) Int(key string) int { | |
if v, err := strconv.Atoi(m[key]); err == nil { | |
return v | |
} | |
return 0 | |
} | |
func (m mockFlags) Bool(key string) bool { | |
if v, err := strconv.ParseBool(m[key]); err == nil { | |
return v | |
} | |
return false | |
} | |
func (m mockFlags) IsSet(key string) bool { | |
_, gotIt := m[key] | |
return gotIt | |
} | |
func (m mockFlags) getCopy() mockFlags { | |
r := mockFlags{} | |
for k, v := range m { | |
r[k] = v | |
} | |
return r | |
} | |
func (m mockFlags) copyWithout(keys ...string) mockFlags { | |
r := m.getCopy() | |
for _, k := range keys { | |
delete(r, k) | |
} | |
return r | |
} | |
func (m mockFlags) update(key, value string) mockFlags { | |
m[key] = value | |
return m | |
} | |
type mockCfg Config | |
func (c *mockCfg) setTLSCert(tlsCertPath string) *mockCfg { | |
c.Control.TLSCertPath = tlsCertPath | |
return c | |
} | |
func (c *mockCfg) setTLSKey(tlsKeyPath string) *mockCfg { | |
c.Control.TLSKeyPath = tlsKeyPath | |
return c | |
} | |
func (c *mockCfg) setCACertPaths(caCertPaths string) *mockCfg { | |
c.Control.CACertPaths = caCertPaths | |
return c | |
} | |
func (c *mockCfg) setApiAddr(apiAddr string) *mockCfg { | |
c.RestAPI.Address = apiAddr | |
return c | |
} | |
func (c *mockCfg) getCopy() (r *mockCfg) { | |
r = &mockCfg{} | |
b, err := json.Marshal(*c) | |
if err != nil { | |
panic(err) | |
} | |
err = json.Unmarshal(b, r) | |
if err != nil { | |
panic(err) | |
} | |
return r | |
} | |
func (c *mockCfg) export() *Config { | |
return (*Config)(c) | |
} | |
func Test_checkCmdLineFlags(t *testing.T) { | |
testCtx := mockFlags{ | |
"tls-cert": "mock-cli.crt", | |
"tls-key": "mock-cli.key", | |
"ca-cert-paths": "mock-ca.crt", | |
"api-addr": "localhost", | |
"api-port": "9000"} | |
tests := []struct { | |
name string | |
msg func(func(string)) | |
ctx runtimeFlagsContext | |
wantErr bool | |
wantPort int | |
wantPortInAddr bool | |
}{ | |
{name: "CmdlineArgsParseWell", | |
msg: func(f func(string)) { | |
f("Having valid command line flags, parsing succeeds") | |
}, | |
ctx: testCtx.getCopy(), | |
wantErr: false, | |
wantPort: 9000, | |
wantPortInAddr: false}, | |
{name: "CmdlineArgsWithoutTLSConfigParseWell", | |
msg: func(f func(string)) { | |
f("Having valid command line flags without any TLS parameters, parsing succeeds") | |
}, | |
ctx: testCtx. | |
copyWithout("tls-cert", "tls-key", "ca-cert-paths", "api-port"). | |
update("api-addr", "127.0.0.1:9002"), | |
wantErr: false, | |
wantPort: 9002, | |
wantPortInAddr: true}, | |
{name: "ArgsWithTLSCertWithoutKey_Fail", | |
msg: func(f func(string)) { | |
f("Having command line flags with TLS cert without key, parsing fails") | |
}, | |
ctx: testCtx.copyWithout("tls-key"), | |
wantErr: true, | |
}, | |
{name: "ArgsWithTLSKeyWithoutCert_Fail", | |
msg: func(f func(string)) { | |
f("Having command line flags with TLS key without cert, parsing fails") | |
}, | |
ctx: testCtx.copyWithout("tls-cert"), | |
wantErr: true, | |
}, | |
} | |
for _, tc := range tests { | |
runThisCase := func(f func(msg string)) { | |
t.Run(tc.name, func(_ *testing.T) { | |
tc.msg(f) | |
}) | |
} | |
runThisCase(func(msg string) { | |
Convey(msg, t, func() { | |
gotPort, gotPortInAddr, err := checkCmdLineFlags(tc.ctx) | |
if tc.wantErr { | |
So(err, ShouldNotBeNil) | |
return | |
} | |
So(err, ShouldBeNil) | |
So(gotPort, ShouldEqual, tc.wantPort) | |
So(gotPortInAddr, ShouldEqual, tc.wantPortInAddr) | |
}) | |
}) | |
} | |
} | |
func Test_checkCfgSettings(t *testing.T) { | |
const DontCheckInt = -99 | |
testCfg := &mockCfg{ | |
Control: &control.Config{}, | |
RestAPI: &rest.Config{}, | |
} | |
tests := []struct { | |
name string | |
msg func(func(string)) | |
cfg *Config | |
wantErr bool | |
wantPort int | |
wantPortInAddr bool | |
}{ | |
{name: "DefaultConfigSettingsValidateWell", | |
msg: func(f func(string)) { | |
f("Having all default (empty) values for config, validation succeeds") | |
}, | |
cfg: (&mockCfg{Control: control.GetDefaultConfig(), RestAPI: rest.GetDefaultConfig()}).export(), | |
wantErr: false, | |
wantPort: DontCheckInt, | |
wantPortInAddr: false}, | |
{name: "ConfigSettingsValidateWell", | |
msg: func(f func(string)) { | |
f("Having correct values, config validation succeeds") | |
}, | |
cfg: testCfg.getCopy(). | |
setApiAddr("localhost:9000"). | |
setTLSCert("mock-cli.crt"). | |
setTLSKey("mock-cli.key"). | |
setCACertPaths("mock-ca.crt"). | |
export(), | |
wantErr: false, | |
wantPort: 9000, | |
wantPortInAddr: true}, | |
{name: "ConfigSettingsWithoutTLSConfigValidateWell", | |
msg: func(f func(string)) { | |
f("Having correct values without any TLS parameters, config validation succeeds") | |
}, | |
cfg: testCfg.getCopy(). | |
setApiAddr("localhost:9000"). | |
export(), | |
wantErr: false, | |
wantPort: 9000, | |
wantPortInAddr: true}, | |
{name: "ConfigSettingsWithTLSCertWithoutKey_Fail", | |
msg: func(f func(string)) { | |
f("Having config with TLS cert without key, config fails to validate") | |
}, | |
cfg: testCfg.getCopy(). | |
setApiAddr("localhost:9000"). | |
setTLSCert("mock-cli.crt"). | |
export(), | |
wantErr: true, | |
wantPort: 9000, | |
wantPortInAddr: true}, | |
{name: "ConfigSettingsWithTLSKeyWithoutCert_Fail", | |
msg: func(f func(string)) { | |
f("Having config with TLS key without cert, config fails to validate") | |
}, | |
cfg: testCfg.getCopy(). | |
setApiAddr("localhost:9000"). | |
setTLSKey("mock-cli.crt"). | |
export(), | |
wantErr: true, | |
wantPort: 9000, | |
wantPortInAddr: true}, | |
} | |
for _, tc := range tests { | |
runThisCase := func(f func(msg string)) { | |
t.Run(tc.name, func(_ *testing.T) { | |
tc.msg(f) | |
}) | |
} | |
runThisCase(func(msg string) { | |
Convey(msg, t, func() { | |
gotPort, gotPortInAddr, err := checkCfgSettings(tc.cfg) | |
if tc.wantErr { | |
So(err, ShouldNotBeNil) | |
return | |
} | |
So(err, ShouldBeNil) | |
if tc.wantPort != DontCheckInt { | |
So(gotPort, ShouldEqual, tc.wantPort) | |
} | |
So(gotPortInAddr, ShouldEqual, tc.wantPortInAddr) | |
}) | |
}) | |
} | |
} | |
func Test_applyCmdLineFlags(t *testing.T) { | |
Convey("Having arguments given on command line", t, func() { | |
gotConfig := Config{ | |
Control: &control.Config{}, | |
RestAPI: &rest.Config{}, | |
Tribe: &tribe.Config{}, | |
Scheduler: &scheduler.Config{}, | |
} | |
applyCmdLineFlags(&gotConfig, validCmdlineFlags_input) | |
Convey("config should be filled with correct values", func() { | |
So(*gotConfig.Control, ShouldResemble, *validCmdlineFlags_expected.Control) | |
So(*gotConfig.RestAPI, ShouldResemble, *validCmdlineFlags_expected.RestAPI) | |
So(*gotConfig.Tribe, ShouldResemble, *validCmdlineFlags_expected.Tribe) | |
So(*gotConfig.Scheduler, ShouldResemble, *validCmdlineFlags_expected.Scheduler) | |
So(gotConfig, ShouldResemble, *validCmdlineFlags_expected) | |
}) | |
}) | |
} |