Fix the dependency issue (#231)
This commit is contained in:
6
vendor/github.com/magiconair/properties/.gitignore
generated
vendored
6
vendor/github.com/magiconair/properties/.gitignore
generated
vendored
@@ -1,6 +0,0 @@
|
||||
*.sublime-project
|
||||
*.sublime-workspace
|
||||
*.un~
|
||||
*.swp
|
||||
.idea/
|
||||
*.iml
|
||||
8
vendor/github.com/magiconair/properties/.travis.yml
generated
vendored
8
vendor/github.com/magiconair/properties/.travis.yml
generated
vendored
@@ -1,8 +0,0 @@
|
||||
language: go
|
||||
go:
|
||||
- 1.4.x
|
||||
- 1.5.x
|
||||
- 1.6.x
|
||||
- 1.7.x
|
||||
- 1.8.x
|
||||
- tip
|
||||
96
vendor/github.com/magiconair/properties/CHANGELOG.md
generated
vendored
96
vendor/github.com/magiconair/properties/CHANGELOG.md
generated
vendored
@@ -1,96 +0,0 @@
|
||||
## Changelog
|
||||
|
||||
### [1.7.3](https://github.com/magiconair/properties/tags/v1.7.3) - 10 Jul 2017
|
||||
|
||||
* [Issue #17](https://github.com/magiconair/properties/issues/17): Add [SetValue()](http://godoc.org/github.com/magiconair/properties#Properties.SetValue) method to set values generically
|
||||
* [Issue #22](https://github.com/magiconair/properties/issues/22): Add [LoadMap()](http://godoc.org/github.com/magiconair/properties#LoadMap) function to load properties from a string map
|
||||
|
||||
### [1.7.2](https://github.com/magiconair/properties/tags/v1.7.2) - 20 Mar 2017
|
||||
|
||||
* [Issue #15](https://github.com/magiconair/properties/issues/15): Drop gocheck dependency
|
||||
* [PR #21](https://github.com/magiconair/properties/pull/21): Add [Map()](http://godoc.org/github.com/magiconair/properties#Properties.Map) and [FilterFunc()](http://godoc.org/github.com/magiconair/properties#Properties.FilterFunc)
|
||||
|
||||
### [1.7.1](https://github.com/magiconair/properties/tags/v1.7.1) - 13 Jan 2017
|
||||
|
||||
* [PR #16](https://github.com/magiconair/properties/pull/16): Keep gofmt happy
|
||||
* [PR #18](https://github.com/magiconair/properties/pull/18): Fix Delete() function
|
||||
|
||||
### [1.7.0](https://github.com/magiconair/properties/tags/v1.7.0) - 20 Mar 2016
|
||||
|
||||
* [Issue #10](https://github.com/magiconair/properties/issues/10): Add [LoadURL,LoadURLs,MustLoadURL,MustLoadURLs](http://godoc.org/github.com/magiconair/properties#LoadURL) method to load properties from a URL.
|
||||
* [Issue #11](https://github.com/magiconair/properties/issues/11): Add [LoadString,MustLoadString](http://godoc.org/github.com/magiconair/properties#LoadString) method to load properties from an UTF8 string.
|
||||
* [PR #8](https://github.com/magiconair/properties/pull/8): Add [MustFlag](http://godoc.org/github.com/magiconair/properties#Properties.MustFlag) method to provide overrides via command line flags. (@pascaldekloe)
|
||||
|
||||
### [1.6.0](https://github.com/magiconair/properties/tags/v1.6.0) - 11 Dec 2015
|
||||
|
||||
* Add [Decode](http://godoc.org/github.com/magiconair/properties#Properties.Decode) method to populate struct from properties via tags.
|
||||
|
||||
### [1.5.6](https://github.com/magiconair/properties/tags/v1.5.6) - 18 Oct 2015
|
||||
|
||||
* Vendored in gopkg.in/check.v1
|
||||
|
||||
### [1.5.5](https://github.com/magiconair/properties/tags/v1.5.5) - 31 Jul 2015
|
||||
|
||||
* [PR #6](https://github.com/magiconair/properties/pull/6): Add [Delete](http://godoc.org/github.com/magiconair/properties#Properties.Delete) method to remove keys including comments. (@gerbenjacobs)
|
||||
|
||||
### [1.5.4](https://github.com/magiconair/properties/tags/v1.5.4) - 23 Jun 2015
|
||||
|
||||
* [Issue #5](https://github.com/magiconair/properties/issues/5): Allow disabling of property expansion [DisableExpansion](http://godoc.org/github.com/magiconair/properties#Properties.DisableExpansion). When property expansion is disabled Properties become a simple key/value store and don't check for circular references.
|
||||
|
||||
### [1.5.3](https://github.com/magiconair/properties/tags/v1.5.3) - 02 Jun 2015
|
||||
|
||||
* [Issue #4](https://github.com/magiconair/properties/issues/4): Maintain key order in [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) and [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp)
|
||||
|
||||
### [1.5.2](https://github.com/magiconair/properties/tags/v1.5.2) - 10 Apr 2015
|
||||
|
||||
* [Issue #3](https://github.com/magiconair/properties/issues/3): Don't print comments in [WriteComment()](http://godoc.org/github.com/magiconair/properties#Properties.WriteComment) if they are all empty
|
||||
* Add clickable links to README
|
||||
|
||||
### [1.5.1](https://github.com/magiconair/properties/tags/v1.5.1) - 08 Dec 2014
|
||||
|
||||
* Added [GetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.GetParsedDuration) and [MustGetParsedDuration()](http://godoc.org/github.com/magiconair/properties#Properties.MustGetParsedDuration) for values specified compatible with
|
||||
[time.ParseDuration()](http://golang.org/pkg/time/#ParseDuration).
|
||||
|
||||
### [1.5.0](https://github.com/magiconair/properties/tags/v1.5.0) - 18 Nov 2014
|
||||
|
||||
* Added support for single and multi-line comments (reading, writing and updating)
|
||||
* The order of keys is now preserved
|
||||
* Calling [Set()](http://godoc.org/github.com/magiconair/properties#Properties.Set) with an empty key now silently ignores the call and does not create a new entry
|
||||
* Added a [MustSet()](http://godoc.org/github.com/magiconair/properties#Properties.MustSet) method
|
||||
* Migrated test library from launchpad.net/gocheck to [gopkg.in/check.v1](http://gopkg.in/check.v1)
|
||||
|
||||
### [1.4.2](https://github.com/magiconair/properties/tags/v1.4.2) - 15 Nov 2014
|
||||
|
||||
* [Issue #2](https://github.com/magiconair/properties/issues/2): Fixed goroutine leak in parser which created two lexers but cleaned up only one
|
||||
|
||||
### [1.4.1](https://github.com/magiconair/properties/tags/v1.4.1) - 13 Nov 2014
|
||||
|
||||
* [Issue #1](https://github.com/magiconair/properties/issues/1): Fixed bug in Keys() method which returned an empty string
|
||||
|
||||
### [1.4.0](https://github.com/magiconair/properties/tags/v1.4.0) - 23 Sep 2014
|
||||
|
||||
* Added [Keys()](http://godoc.org/github.com/magiconair/properties#Properties.Keys) to get the keys
|
||||
* Added [Filter()](http://godoc.org/github.com/magiconair/properties#Properties.Filter), [FilterRegexp()](http://godoc.org/github.com/magiconair/properties#Properties.FilterRegexp) and [FilterPrefix()](http://godoc.org/github.com/magiconair/properties#Properties.FilterPrefix) to get a subset of the properties
|
||||
|
||||
### [1.3.0](https://github.com/magiconair/properties/tags/v1.3.0) - 18 Mar 2014
|
||||
|
||||
* Added support for time.Duration
|
||||
* Made MustXXX() failure beha[ior configurable (log.Fatal, panic](https://github.com/magiconair/properties/tags/vior configurable (log.Fatal, panic) - custom)
|
||||
* Changed default of MustXXX() failure from panic to log.Fatal
|
||||
|
||||
### [1.2.0](https://github.com/magiconair/properties/tags/v1.2.0) - 05 Mar 2014
|
||||
|
||||
* Added MustGet... functions
|
||||
* Added support for int and uint with range checks on 32 bit platforms
|
||||
|
||||
### [1.1.0](https://github.com/magiconair/properties/tags/v1.1.0) - 20 Jan 2014
|
||||
|
||||
* Renamed from goproperties to properties
|
||||
* Added support for expansion of environment vars in
|
||||
filenames and value expressions
|
||||
* Fixed bug where value expressions were not at the
|
||||
start of the string
|
||||
|
||||
### [1.0.0](https://github.com/magiconair/properties/tags/v1.0.0) - 7 Jan 2014
|
||||
|
||||
* Initial release
|
||||
2
vendor/github.com/magiconair/properties/LICENSE
generated
vendored
2
vendor/github.com/magiconair/properties/LICENSE
generated
vendored
@@ -1,6 +1,6 @@
|
||||
goproperties - properties file decoder for Go
|
||||
|
||||
Copyright (c) 2013-2014 - Frank Schroeder
|
||||
Copyright (c) 2013-2018 - Frank Schroeder
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
||||
100
vendor/github.com/magiconair/properties/README.md
generated
vendored
100
vendor/github.com/magiconair/properties/README.md
generated
vendored
@@ -1,100 +0,0 @@
|
||||
Overview [](https://travis-ci.org/magiconair/properties)
|
||||
========
|
||||
|
||||
#### Current version: 1.7.3
|
||||
|
||||
properties is a Go library for reading and writing properties files.
|
||||
|
||||
It supports reading from multiple files or URLs and Spring style recursive
|
||||
property expansion of expressions like `${key}` to their corresponding value.
|
||||
Value expressions can refer to other keys like in `${key}` or to environment
|
||||
variables like in `${USER}`. Filenames can also contain environment variables
|
||||
like in `/home/${USER}/myapp.properties`.
|
||||
|
||||
Properties can be decoded into structs, maps, arrays and values through
|
||||
struct tags.
|
||||
|
||||
Comments and the order of keys are preserved. Comments can be modified
|
||||
and can be written to the output.
|
||||
|
||||
The properties library supports both ISO-8859-1 and UTF-8 encoded data.
|
||||
|
||||
Starting from version 1.3.0 the behavior of the MustXXX() functions is
|
||||
configurable by providing a custom `ErrorHandler` function. The default has
|
||||
changed from `panic` to `log.Fatal` but this is configurable and custom
|
||||
error handling functions can be provided. See the package documentation for
|
||||
details.
|
||||
|
||||
Read the full documentation on [GoDoc](https://godoc.org/github.com/magiconair/properties) [](https://godoc.org/github.com/magiconair/properties)
|
||||
|
||||
Getting Started
|
||||
---------------
|
||||
|
||||
```go
|
||||
import (
|
||||
"flag"
|
||||
"github.com/magiconair/properties"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// init from a file
|
||||
p := properties.MustLoadFile("${HOME}/config.properties", properties.UTF8)
|
||||
|
||||
// or multiple files
|
||||
p = properties.MustLoadFiles([]string{
|
||||
"${HOME}/config.properties",
|
||||
"${HOME}/config-${USER}.properties",
|
||||
}, properties.UTF8, true)
|
||||
|
||||
// or from a map
|
||||
p = properties.LoadMap(map[string]string{"key": "value", "abc": "def"})
|
||||
|
||||
// or from a string
|
||||
p = properties.MustLoadString("key=value\nabc=def")
|
||||
|
||||
// or from a URL
|
||||
p = properties.MustLoadURL("http://host/path")
|
||||
|
||||
// or from multiple URLs
|
||||
p = properties.MustLoadURL([]string{
|
||||
"http://host/config",
|
||||
"http://host/config-${USER}",
|
||||
}, true)
|
||||
|
||||
// or from flags
|
||||
p.MustFlag(flag.CommandLine)
|
||||
|
||||
// get values through getters
|
||||
host := p.MustGetString("host")
|
||||
port := p.GetInt("port", 8080)
|
||||
|
||||
// or through Decode
|
||||
type Config struct {
|
||||
Host string `properties:"host"`
|
||||
Port int `properties:"port,default=9000"`
|
||||
Accept []string `properties:"accept,default=image/png;image;gif"`
|
||||
Timeout time.Duration `properties:"timeout,default=5s"`
|
||||
}
|
||||
var cfg Config
|
||||
if err := p.Decode(&cfg); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Installation and Upgrade
|
||||
------------------------
|
||||
|
||||
```
|
||||
$ go get -u github.com/magiconair/properties
|
||||
```
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
2 clause BSD license. See [LICENSE](https://github.com/magiconair/properties/blob/master/LICENSE) file for details.
|
||||
|
||||
ToDo
|
||||
----
|
||||
* Dump contents with passwords and secrets obscured
|
||||
90
vendor/github.com/magiconair/properties/assert/assert.go
generated
vendored
90
vendor/github.com/magiconair/properties/assert/assert.go
generated
vendored
@@ -1,90 +0,0 @@
|
||||
// Copyright 2017 Frank Schroeder. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package assert provides helper functions for testing.
|
||||
package assert
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// skip defines the default call depth
|
||||
const skip = 2
|
||||
|
||||
// Equal asserts that got and want are equal as defined by
|
||||
// reflect.DeepEqual. The test fails with msg if they are not equal.
|
||||
func Equal(t *testing.T, got, want interface{}, msg ...string) {
|
||||
if x := equal(2, got, want, msg...); x != "" {
|
||||
fmt.Println(x)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func equal(skip int, got, want interface{}, msg ...string) string {
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
return fail(skip, "got %v want %v %s", got, want, strings.Join(msg, " "))
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Panic asserts that function fn() panics.
|
||||
// It assumes that recover() either returns a string or
|
||||
// an error and fails if the message does not match
|
||||
// the regular expression in 'matches'.
|
||||
func Panic(t *testing.T, fn func(), matches string) {
|
||||
if x := doesPanic(2, fn, matches); x != "" {
|
||||
fmt.Println(x)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func doesPanic(skip int, fn func(), expr string) (err string) {
|
||||
defer func() {
|
||||
r := recover()
|
||||
if r == nil {
|
||||
err = fail(skip, "did not panic")
|
||||
return
|
||||
}
|
||||
var v string
|
||||
switch r.(type) {
|
||||
case error:
|
||||
v = r.(error).Error()
|
||||
case string:
|
||||
v = r.(string)
|
||||
}
|
||||
err = matches(skip, v, expr)
|
||||
}()
|
||||
fn()
|
||||
return ""
|
||||
}
|
||||
|
||||
// Matches asserts that a value matches a given regular expression.
|
||||
func Matches(t *testing.T, value, expr string) {
|
||||
if x := matches(2, value, expr); x != "" {
|
||||
fmt.Println(x)
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func matches(skip int, value, expr string) string {
|
||||
ok, err := regexp.MatchString(expr, value)
|
||||
if err != nil {
|
||||
return fail(skip, "invalid pattern %q. %s", expr, err)
|
||||
}
|
||||
if !ok {
|
||||
return fail(skip, "got %s which does not match %s", value, expr)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func fail(skip int, format string, args ...interface{}) string {
|
||||
_, file, line, _ := runtime.Caller(skip)
|
||||
return fmt.Sprintf("\t%s:%d: %s\n", filepath.Base(file), line, fmt.Sprintf(format, args...))
|
||||
}
|
||||
55
vendor/github.com/magiconair/properties/assert/assert_test.go
generated
vendored
55
vendor/github.com/magiconair/properties/assert/assert_test.go
generated
vendored
@@ -1,55 +0,0 @@
|
||||
// Copyright 2017 Frank Schroeder. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package assert
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestEqualEquals(t *testing.T) {
|
||||
if got, want := equal(2, "a", "a"), ""; got != want {
|
||||
t.Fatalf("got %q want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEqualFails(t *testing.T) {
|
||||
if got, want := equal(2, "a", "b"), "\tassert_test.go:16: got a want b \n"; got != want {
|
||||
t.Fatalf("got %q want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPanicPanics(t *testing.T) {
|
||||
if got, want := doesPanic(2, func() { panic("foo") }, ""), ""; got != want {
|
||||
t.Fatalf("got %q want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPanicPanicsAndMatches(t *testing.T) {
|
||||
if got, want := doesPanic(2, func() { panic("foo") }, "foo"), ""; got != want {
|
||||
t.Fatalf("got %q want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPanicPanicsAndDoesNotMatch(t *testing.T) {
|
||||
if got, want := doesPanic(2, func() { panic("foo") }, "bar"), "\tassert.go:62: got foo which does not match bar\n"; got != want {
|
||||
t.Fatalf("got %q want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPanicPanicsAndDoesNotPanic(t *testing.T) {
|
||||
if got, want := doesPanic(2, func() {}, "bar"), "\tassert.go:65: did not panic\n"; got != want {
|
||||
t.Fatalf("got %q want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatchesMatches(t *testing.T) {
|
||||
if got, want := matches(2, "aaa", "a"), ""; got != want {
|
||||
t.Fatalf("got %q want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatchesDoesNotMatch(t *testing.T) {
|
||||
if got, want := matches(2, "aaa", "b"), "\tassert_test.go:52: got aaa which does not match b\n"; got != want {
|
||||
t.Fatalf("got %q want %q", got, want)
|
||||
}
|
||||
}
|
||||
24
vendor/github.com/magiconair/properties/benchmark_test.go
generated
vendored
24
vendor/github.com/magiconair/properties/benchmark_test.go
generated
vendored
@@ -1,24 +0,0 @@
|
||||
// Copyright 2013-2014 Frank Schroeder. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package properties
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// Benchmarks the decoder by creating a property file with 1000 key/value pairs.
|
||||
func BenchmarkLoad(b *testing.B) {
|
||||
input := ""
|
||||
for i := 0; i < 1000; i++ {
|
||||
input += fmt.Sprintf("key%d=value%d\n", i, i)
|
||||
}
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := Load([]byte(input), ISO_8859_1); err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
299
vendor/github.com/magiconair/properties/decode_test.go
generated
vendored
299
vendor/github.com/magiconair/properties/decode_test.go
generated
vendored
@@ -1,299 +0,0 @@
|
||||
// Copyright 2017 Frank Schroeder. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package properties
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestDecodeValues(t *testing.T) {
|
||||
type S struct {
|
||||
S string
|
||||
BT bool
|
||||
BF bool
|
||||
I int
|
||||
I8 int8
|
||||
I16 int16
|
||||
I32 int32
|
||||
I64 int64
|
||||
U uint
|
||||
U8 uint8
|
||||
U16 uint16
|
||||
U32 uint32
|
||||
U64 uint64
|
||||
F32 float32
|
||||
F64 float64
|
||||
D time.Duration
|
||||
TM time.Time
|
||||
}
|
||||
in := `
|
||||
S=abc
|
||||
BT=true
|
||||
BF=false
|
||||
I=-1
|
||||
I8=-8
|
||||
I16=-16
|
||||
I32=-32
|
||||
I64=-64
|
||||
U=1
|
||||
U8=8
|
||||
U16=16
|
||||
U32=32
|
||||
U64=64
|
||||
F32=3.2
|
||||
F64=6.4
|
||||
D=5s
|
||||
TM=2015-01-02T12:34:56Z
|
||||
`
|
||||
out := &S{
|
||||
S: "abc",
|
||||
BT: true,
|
||||
BF: false,
|
||||
I: -1,
|
||||
I8: -8,
|
||||
I16: -16,
|
||||
I32: -32,
|
||||
I64: -64,
|
||||
U: 1,
|
||||
U8: 8,
|
||||
U16: 16,
|
||||
U32: 32,
|
||||
U64: 64,
|
||||
F32: 3.2,
|
||||
F64: 6.4,
|
||||
D: 5 * time.Second,
|
||||
TM: tm(t, time.RFC3339, "2015-01-02T12:34:56Z"),
|
||||
}
|
||||
testDecode(t, in, &S{}, out)
|
||||
}
|
||||
|
||||
func TestDecodeValueDefaults(t *testing.T) {
|
||||
type S struct {
|
||||
S string `properties:",default=abc"`
|
||||
BT bool `properties:",default=true"`
|
||||
BF bool `properties:",default=false"`
|
||||
I int `properties:",default=-1"`
|
||||
I8 int8 `properties:",default=-8"`
|
||||
I16 int16 `properties:",default=-16"`
|
||||
I32 int32 `properties:",default=-32"`
|
||||
I64 int64 `properties:",default=-64"`
|
||||
U uint `properties:",default=1"`
|
||||
U8 uint8 `properties:",default=8"`
|
||||
U16 uint16 `properties:",default=16"`
|
||||
U32 uint32 `properties:",default=32"`
|
||||
U64 uint64 `properties:",default=64"`
|
||||
F32 float32 `properties:",default=3.2"`
|
||||
F64 float64 `properties:",default=6.4"`
|
||||
D time.Duration `properties:",default=5s"`
|
||||
TM time.Time `properties:",default=2015-01-02T12:34:56Z"`
|
||||
}
|
||||
out := &S{
|
||||
S: "abc",
|
||||
BT: true,
|
||||
BF: false,
|
||||
I: -1,
|
||||
I8: -8,
|
||||
I16: -16,
|
||||
I32: -32,
|
||||
I64: -64,
|
||||
U: 1,
|
||||
U8: 8,
|
||||
U16: 16,
|
||||
U32: 32,
|
||||
U64: 64,
|
||||
F32: 3.2,
|
||||
F64: 6.4,
|
||||
D: 5 * time.Second,
|
||||
TM: tm(t, time.RFC3339, "2015-01-02T12:34:56Z"),
|
||||
}
|
||||
testDecode(t, "", &S{}, out)
|
||||
}
|
||||
|
||||
func TestDecodeArrays(t *testing.T) {
|
||||
type S struct {
|
||||
S []string
|
||||
B []bool
|
||||
I []int
|
||||
I8 []int8
|
||||
I16 []int16
|
||||
I32 []int32
|
||||
I64 []int64
|
||||
U []uint
|
||||
U8 []uint8
|
||||
U16 []uint16
|
||||
U32 []uint32
|
||||
U64 []uint64
|
||||
F32 []float32
|
||||
F64 []float64
|
||||
D []time.Duration
|
||||
TM []time.Time
|
||||
}
|
||||
in := `
|
||||
S=a;b
|
||||
B=true;false
|
||||
I=-1;-2
|
||||
I8=-8;-9
|
||||
I16=-16;-17
|
||||
I32=-32;-33
|
||||
I64=-64;-65
|
||||
U=1;2
|
||||
U8=8;9
|
||||
U16=16;17
|
||||
U32=32;33
|
||||
U64=64;65
|
||||
F32=3.2;3.3
|
||||
F64=6.4;6.5
|
||||
D=4s;5s
|
||||
TM=2015-01-01T00:00:00Z;2016-01-01T00:00:00Z
|
||||
`
|
||||
out := &S{
|
||||
S: []string{"a", "b"},
|
||||
B: []bool{true, false},
|
||||
I: []int{-1, -2},
|
||||
I8: []int8{-8, -9},
|
||||
I16: []int16{-16, -17},
|
||||
I32: []int32{-32, -33},
|
||||
I64: []int64{-64, -65},
|
||||
U: []uint{1, 2},
|
||||
U8: []uint8{8, 9},
|
||||
U16: []uint16{16, 17},
|
||||
U32: []uint32{32, 33},
|
||||
U64: []uint64{64, 65},
|
||||
F32: []float32{3.2, 3.3},
|
||||
F64: []float64{6.4, 6.5},
|
||||
D: []time.Duration{4 * time.Second, 5 * time.Second},
|
||||
TM: []time.Time{tm(t, time.RFC3339, "2015-01-01T00:00:00Z"), tm(t, time.RFC3339, "2016-01-01T00:00:00Z")},
|
||||
}
|
||||
testDecode(t, in, &S{}, out)
|
||||
}
|
||||
|
||||
func TestDecodeArrayDefaults(t *testing.T) {
|
||||
type S struct {
|
||||
S []string `properties:",default=a;b"`
|
||||
B []bool `properties:",default=true;false"`
|
||||
I []int `properties:",default=-1;-2"`
|
||||
I8 []int8 `properties:",default=-8;-9"`
|
||||
I16 []int16 `properties:",default=-16;-17"`
|
||||
I32 []int32 `properties:",default=-32;-33"`
|
||||
I64 []int64 `properties:",default=-64;-65"`
|
||||
U []uint `properties:",default=1;2"`
|
||||
U8 []uint8 `properties:",default=8;9"`
|
||||
U16 []uint16 `properties:",default=16;17"`
|
||||
U32 []uint32 `properties:",default=32;33"`
|
||||
U64 []uint64 `properties:",default=64;65"`
|
||||
F32 []float32 `properties:",default=3.2;3.3"`
|
||||
F64 []float64 `properties:",default=6.4;6.5"`
|
||||
D []time.Duration `properties:",default=4s;5s"`
|
||||
TM []time.Time `properties:",default=2015-01-01T00:00:00Z;2016-01-01T00:00:00Z"`
|
||||
}
|
||||
out := &S{
|
||||
S: []string{"a", "b"},
|
||||
B: []bool{true, false},
|
||||
I: []int{-1, -2},
|
||||
I8: []int8{-8, -9},
|
||||
I16: []int16{-16, -17},
|
||||
I32: []int32{-32, -33},
|
||||
I64: []int64{-64, -65},
|
||||
U: []uint{1, 2},
|
||||
U8: []uint8{8, 9},
|
||||
U16: []uint16{16, 17},
|
||||
U32: []uint32{32, 33},
|
||||
U64: []uint64{64, 65},
|
||||
F32: []float32{3.2, 3.3},
|
||||
F64: []float64{6.4, 6.5},
|
||||
D: []time.Duration{4 * time.Second, 5 * time.Second},
|
||||
TM: []time.Time{tm(t, time.RFC3339, "2015-01-01T00:00:00Z"), tm(t, time.RFC3339, "2016-01-01T00:00:00Z")},
|
||||
}
|
||||
testDecode(t, "", &S{}, out)
|
||||
}
|
||||
|
||||
func TestDecodeSkipUndef(t *testing.T) {
|
||||
type S struct {
|
||||
X string `properties:"-"`
|
||||
Undef string `properties:",default=some value"`
|
||||
}
|
||||
in := `X=ignore`
|
||||
out := &S{"", "some value"}
|
||||
testDecode(t, in, &S{}, out)
|
||||
}
|
||||
|
||||
func TestDecodeStruct(t *testing.T) {
|
||||
type A struct {
|
||||
S string
|
||||
T string `properties:"t"`
|
||||
U string `properties:"u,default=uuu"`
|
||||
}
|
||||
type S struct {
|
||||
A A
|
||||
B A `properties:"b"`
|
||||
}
|
||||
in := `
|
||||
A.S=sss
|
||||
A.t=ttt
|
||||
b.S=SSS
|
||||
b.t=TTT
|
||||
`
|
||||
out := &S{
|
||||
A{S: "sss", T: "ttt", U: "uuu"},
|
||||
A{S: "SSS", T: "TTT", U: "uuu"},
|
||||
}
|
||||
testDecode(t, in, &S{}, out)
|
||||
}
|
||||
|
||||
func TestDecodeMap(t *testing.T) {
|
||||
type S struct {
|
||||
A string `properties:"a"`
|
||||
}
|
||||
type X struct {
|
||||
A map[string]string
|
||||
B map[string][]string
|
||||
C map[string]map[string]string
|
||||
D map[string]S
|
||||
E map[string]int
|
||||
F map[string]int `properties:"-"`
|
||||
}
|
||||
in := `
|
||||
A.foo=bar
|
||||
A.bar=bang
|
||||
B.foo=a;b;c
|
||||
B.bar=1;2;3
|
||||
C.foo.one=1
|
||||
C.foo.two=2
|
||||
C.bar.three=3
|
||||
C.bar.four=4
|
||||
D.foo.a=bar
|
||||
`
|
||||
out := &X{
|
||||
A: map[string]string{"foo": "bar", "bar": "bang"},
|
||||
B: map[string][]string{"foo": []string{"a", "b", "c"}, "bar": []string{"1", "2", "3"}},
|
||||
C: map[string]map[string]string{"foo": map[string]string{"one": "1", "two": "2"}, "bar": map[string]string{"three": "3", "four": "4"}},
|
||||
D: map[string]S{"foo": S{"bar"}},
|
||||
E: map[string]int{},
|
||||
}
|
||||
testDecode(t, in, &X{}, out)
|
||||
}
|
||||
|
||||
func testDecode(t *testing.T, in string, v, out interface{}) {
|
||||
p, err := parse(in)
|
||||
if err != nil {
|
||||
t.Fatalf("got %v want nil", err)
|
||||
}
|
||||
if err := p.Decode(v); err != nil {
|
||||
t.Fatalf("got %v want nil", err)
|
||||
}
|
||||
if got, want := v, out; !reflect.DeepEqual(got, want) {
|
||||
t.Fatalf("\ngot %+v\nwant %+v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func tm(t *testing.T, layout, s string) time.Time {
|
||||
tm, err := time.Parse(layout, s)
|
||||
if err != nil {
|
||||
t.Fatalf("got %v want nil", err)
|
||||
}
|
||||
return tm
|
||||
}
|
||||
93
vendor/github.com/magiconair/properties/example_test.go
generated
vendored
93
vendor/github.com/magiconair/properties/example_test.go
generated
vendored
@@ -1,93 +0,0 @@
|
||||
// Copyright 2017 Frank Schroeder. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package properties
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
)
|
||||
|
||||
func ExampleLoad_iso88591() {
|
||||
buf := []byte("key = ISO-8859-1 value with unicode literal \\u2318 and umlaut \xE4") // 0xE4 == ä
|
||||
p, _ := Load(buf, ISO_8859_1)
|
||||
v, ok := p.Get("key")
|
||||
fmt.Println(ok)
|
||||
fmt.Println(v)
|
||||
// Output:
|
||||
// true
|
||||
// ISO-8859-1 value with unicode literal ⌘ and umlaut ä
|
||||
}
|
||||
|
||||
func ExampleLoad_utf8() {
|
||||
p, _ := Load([]byte("key = UTF-8 value with unicode character ⌘ and umlaut ä"), UTF8)
|
||||
v, ok := p.Get("key")
|
||||
fmt.Println(ok)
|
||||
fmt.Println(v)
|
||||
// Output:
|
||||
// true
|
||||
// UTF-8 value with unicode character ⌘ and umlaut ä
|
||||
}
|
||||
|
||||
func ExampleProperties_GetBool() {
|
||||
var input = `
|
||||
key=1
|
||||
key2=On
|
||||
key3=YES
|
||||
key4=true`
|
||||
p, _ := Load([]byte(input), ISO_8859_1)
|
||||
fmt.Println(p.GetBool("key", false))
|
||||
fmt.Println(p.GetBool("key2", false))
|
||||
fmt.Println(p.GetBool("key3", false))
|
||||
fmt.Println(p.GetBool("key4", false))
|
||||
fmt.Println(p.GetBool("keyX", false))
|
||||
// Output:
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// true
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleProperties_GetString() {
|
||||
p, _ := Load([]byte("key=value"), ISO_8859_1)
|
||||
v := p.GetString("another key", "default value")
|
||||
fmt.Println(v)
|
||||
// Output:
|
||||
// default value
|
||||
}
|
||||
|
||||
func Example() {
|
||||
// Decode some key/value pairs with expressions
|
||||
p, err := Load([]byte("key=value\nkey2=${key}"), ISO_8859_1)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Get a valid key
|
||||
if v, ok := p.Get("key"); ok {
|
||||
fmt.Println(v)
|
||||
}
|
||||
|
||||
// Get an invalid key
|
||||
if _, ok := p.Get("does not exist"); !ok {
|
||||
fmt.Println("invalid key")
|
||||
}
|
||||
|
||||
// Get a key with a default value
|
||||
v := p.GetString("does not exist", "some value")
|
||||
fmt.Println(v)
|
||||
|
||||
// Dump the expanded key/value pairs of the Properties
|
||||
fmt.Println("Expanded key/value pairs")
|
||||
fmt.Println(p)
|
||||
|
||||
// Output:
|
||||
// value
|
||||
// invalid key
|
||||
// some value
|
||||
// Expanded key/value pairs
|
||||
// key = value
|
||||
// key2 = value
|
||||
}
|
||||
76
vendor/github.com/magiconair/properties/integrate_test.go
generated
vendored
76
vendor/github.com/magiconair/properties/integrate_test.go
generated
vendored
@@ -1,76 +0,0 @@
|
||||
// Copyright 2017 Frank Schroeder. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package properties
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestFlag verifies Properties.MustFlag without flag.FlagSet.Parse
|
||||
func TestFlag(t *testing.T) {
|
||||
f := flag.NewFlagSet("src", flag.PanicOnError)
|
||||
gotS := f.String("s", "?", "string flag")
|
||||
gotI := f.Int("i", -1, "int flag")
|
||||
|
||||
p := NewProperties()
|
||||
p.MustSet("s", "t")
|
||||
p.MustSet("i", "9")
|
||||
p.MustFlag(f)
|
||||
|
||||
if want := "t"; *gotS != want {
|
||||
t.Errorf("Got string s=%q, want %q", *gotS, want)
|
||||
}
|
||||
if want := 9; *gotI != want {
|
||||
t.Errorf("Got int i=%d, want %d", *gotI, want)
|
||||
}
|
||||
}
|
||||
|
||||
// TestFlagOverride verifies Properties.MustFlag with flag.FlagSet.Parse.
|
||||
func TestFlagOverride(t *testing.T) {
|
||||
f := flag.NewFlagSet("src", flag.PanicOnError)
|
||||
gotA := f.Int("a", 1, "remain default")
|
||||
gotB := f.Int("b", 2, "customized")
|
||||
gotC := f.Int("c", 3, "overridden")
|
||||
|
||||
if err := f.Parse([]string{"-c", "4"}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
p := NewProperties()
|
||||
p.MustSet("b", "5")
|
||||
p.MustSet("c", "6")
|
||||
p.MustFlag(f)
|
||||
|
||||
if want := 1; *gotA != want {
|
||||
t.Errorf("Got remain default a=%d, want %d", *gotA, want)
|
||||
}
|
||||
if want := 5; *gotB != want {
|
||||
t.Errorf("Got customized b=%d, want %d", *gotB, want)
|
||||
}
|
||||
if want := 4; *gotC != want {
|
||||
t.Errorf("Got overriden c=%d, want %d", *gotC, want)
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleProperties_MustFlag() {
|
||||
x := flag.Int("x", 0, "demo customize")
|
||||
y := flag.Int("y", 0, "demo override")
|
||||
|
||||
// Demo alternative for flag.Parse():
|
||||
flag.CommandLine.Parse([]string{"-y", "10"})
|
||||
fmt.Printf("flagged as x=%d, y=%d\n", *x, *y)
|
||||
|
||||
p := NewProperties()
|
||||
p.MustSet("x", "7")
|
||||
p.MustSet("y", "42") // note discard
|
||||
p.MustFlag(flag.CommandLine)
|
||||
fmt.Printf("configured to x=%d, y=%d\n", *x, *y)
|
||||
|
||||
// Output:
|
||||
// flagged as x=0, y=10
|
||||
// configured to x=7, y=10
|
||||
}
|
||||
3
vendor/github.com/magiconair/properties/lex.go
generated
vendored
3
vendor/github.com/magiconair/properties/lex.go
generated
vendored
@@ -196,9 +196,8 @@ func lexBeforeKey(l *lexer) stateFn {
|
||||
return lexComment
|
||||
|
||||
case isWhitespace(r):
|
||||
l.acceptRun(whitespace)
|
||||
l.ignore()
|
||||
return lexKey
|
||||
return lexBeforeKey
|
||||
|
||||
default:
|
||||
l.backup()
|
||||
|
||||
2
vendor/github.com/magiconair/properties/load.go
generated
vendored
2
vendor/github.com/magiconair/properties/load.go
generated
vendored
@@ -218,7 +218,7 @@ func must(p *Properties, err error) *Properties {
|
||||
// with an empty string. Malformed expressions like "${ENV_VAR" will
|
||||
// be reported as error.
|
||||
func expandName(name string) (string, error) {
|
||||
return expand(name, make(map[string]bool), "${", "}", make(map[string]string))
|
||||
return expand(name, []string{}, "${", "}", make(map[string]string))
|
||||
}
|
||||
|
||||
// Interprets a byte buffer either as an ISO-8859-1 or UTF-8 encoded string.
|
||||
|
||||
231
vendor/github.com/magiconair/properties/load_test.go
generated
vendored
231
vendor/github.com/magiconair/properties/load_test.go
generated
vendored
@@ -1,231 +0,0 @@
|
||||
// Copyright 2017 Frank Schroeder. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package properties
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/magiconair/properties/assert"
|
||||
)
|
||||
|
||||
func TestLoadFailsWithNotExistingFile(t *testing.T) {
|
||||
_, err := LoadFile("doesnotexist.properties", ISO_8859_1)
|
||||
assert.Equal(t, err != nil, true, "")
|
||||
assert.Matches(t, err.Error(), "open.*no such file or directory")
|
||||
}
|
||||
|
||||
func TestLoadFilesFailsOnNotExistingFile(t *testing.T) {
|
||||
_, err := LoadFile("doesnotexist.properties", ISO_8859_1)
|
||||
assert.Equal(t, err != nil, true, "")
|
||||
assert.Matches(t, err.Error(), "open.*no such file or directory")
|
||||
}
|
||||
|
||||
func TestLoadFilesDoesNotFailOnNotExistingFileAndIgnoreMissing(t *testing.T) {
|
||||
p, err := LoadFiles([]string{"doesnotexist.properties"}, ISO_8859_1, true)
|
||||
assert.Equal(t, err, nil)
|
||||
assert.Equal(t, p.Len(), 0)
|
||||
}
|
||||
|
||||
func TestLoadString(t *testing.T) {
|
||||
x := "key=äüö"
|
||||
p1 := MustLoadString(x)
|
||||
p2 := must(Load([]byte(x), UTF8))
|
||||
assert.Equal(t, p1, p2)
|
||||
}
|
||||
|
||||
func TestLoadMap(t *testing.T) {
|
||||
// LoadMap does not guarantee the same import order
|
||||
// of keys every time since map access is randomized.
|
||||
// Therefore, we need to compare the generated maps.
|
||||
m := map[string]string{"key": "value", "abc": "def"}
|
||||
assert.Equal(t, LoadMap(m).Map(), m)
|
||||
}
|
||||
|
||||
func TestLoadFile(t *testing.T) {
|
||||
tf := make(tempFiles, 0)
|
||||
defer tf.removeAll()
|
||||
|
||||
filename := tf.makeFile("key=value")
|
||||
p := MustLoadFile(filename, ISO_8859_1)
|
||||
|
||||
assert.Equal(t, p.Len(), 1)
|
||||
assertKeyValues(t, "", p, "key", "value")
|
||||
}
|
||||
|
||||
func TestLoadFiles(t *testing.T) {
|
||||
tf := make(tempFiles, 0)
|
||||
defer tf.removeAll()
|
||||
|
||||
filename := tf.makeFile("key=value")
|
||||
filename2 := tf.makeFile("key2=value2")
|
||||
p := MustLoadFiles([]string{filename, filename2}, ISO_8859_1, false)
|
||||
assertKeyValues(t, "", p, "key", "value", "key2", "value2")
|
||||
}
|
||||
|
||||
func TestLoadExpandedFile(t *testing.T) {
|
||||
tf := make(tempFiles, 0)
|
||||
defer tf.removeAll()
|
||||
|
||||
if err := os.Setenv("_VARX", "some-value"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
filename := tf.makeFilePrefix(os.Getenv("_VARX"), "key=value")
|
||||
filename = strings.Replace(filename, os.Getenv("_VARX"), "${_VARX}", -1)
|
||||
p := MustLoadFile(filename, ISO_8859_1)
|
||||
assertKeyValues(t, "", p, "key", "value")
|
||||
}
|
||||
|
||||
func TestLoadFilesAndIgnoreMissing(t *testing.T) {
|
||||
tf := make(tempFiles, 0)
|
||||
defer tf.removeAll()
|
||||
|
||||
filename := tf.makeFile("key=value")
|
||||
filename2 := tf.makeFile("key2=value2")
|
||||
p := MustLoadFiles([]string{filename, filename + "foo", filename2, filename2 + "foo"}, ISO_8859_1, true)
|
||||
assertKeyValues(t, "", p, "key", "value", "key2", "value2")
|
||||
}
|
||||
|
||||
func TestLoadURL(t *testing.T) {
|
||||
srv := testServer()
|
||||
defer srv.Close()
|
||||
p := MustLoadURL(srv.URL + "/a")
|
||||
assertKeyValues(t, "", p, "key", "value")
|
||||
}
|
||||
|
||||
func TestLoadURLs(t *testing.T) {
|
||||
srv := testServer()
|
||||
defer srv.Close()
|
||||
p := MustLoadURLs([]string{srv.URL + "/a", srv.URL + "/b"}, false)
|
||||
assertKeyValues(t, "", p, "key", "value", "key2", "value2")
|
||||
}
|
||||
|
||||
func TestLoadURLsAndFailMissing(t *testing.T) {
|
||||
srv := testServer()
|
||||
defer srv.Close()
|
||||
p, err := LoadURLs([]string{srv.URL + "/a", srv.URL + "/c"}, false)
|
||||
assert.Equal(t, p, (*Properties)(nil))
|
||||
assert.Matches(t, err.Error(), ".*returned 404.*")
|
||||
}
|
||||
|
||||
func TestLoadURLsAndIgnoreMissing(t *testing.T) {
|
||||
srv := testServer()
|
||||
defer srv.Close()
|
||||
p := MustLoadURLs([]string{srv.URL + "/a", srv.URL + "/b", srv.URL + "/c"}, true)
|
||||
assertKeyValues(t, "", p, "key", "value", "key2", "value2")
|
||||
}
|
||||
|
||||
func TestLoadURLEncoding(t *testing.T) {
|
||||
srv := testServer()
|
||||
defer srv.Close()
|
||||
|
||||
uris := []string{"/none", "/utf8", "/plain", "/latin1", "/iso88591"}
|
||||
for i, uri := range uris {
|
||||
p := MustLoadURL(srv.URL + uri)
|
||||
assert.Equal(t, p.GetString("key", ""), "äöü", fmt.Sprintf("%d", i))
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadURLFailInvalidEncoding(t *testing.T) {
|
||||
srv := testServer()
|
||||
defer srv.Close()
|
||||
|
||||
p, err := LoadURL(srv.URL + "/json")
|
||||
assert.Equal(t, p, (*Properties)(nil))
|
||||
assert.Matches(t, err.Error(), ".*invalid content type.*")
|
||||
}
|
||||
|
||||
func TestLoadAll(t *testing.T) {
|
||||
tf := make(tempFiles, 0)
|
||||
defer tf.removeAll()
|
||||
|
||||
filename := tf.makeFile("key=value")
|
||||
filename2 := tf.makeFile("key2=value3")
|
||||
filename3 := tf.makeFile("key=value4")
|
||||
srv := testServer()
|
||||
defer srv.Close()
|
||||
p := MustLoadAll([]string{filename, filename2, srv.URL + "/a", srv.URL + "/b", filename3}, UTF8, false)
|
||||
assertKeyValues(t, "", p, "key", "value4", "key2", "value2")
|
||||
}
|
||||
|
||||
type tempFiles []string
|
||||
|
||||
func (tf *tempFiles) removeAll() {
|
||||
for _, path := range *tf {
|
||||
err := os.Remove(path)
|
||||
if err != nil {
|
||||
fmt.Printf("os.Remove: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (tf *tempFiles) makeFile(data string) string {
|
||||
return tf.makeFilePrefix("properties", data)
|
||||
}
|
||||
|
||||
func (tf *tempFiles) makeFilePrefix(prefix, data string) string {
|
||||
f, err := ioutil.TempFile("", prefix)
|
||||
if err != nil {
|
||||
panic("ioutil.TempFile: " + err.Error())
|
||||
}
|
||||
|
||||
// remember the temp file so that we can remove it later
|
||||
*tf = append(*tf, f.Name())
|
||||
|
||||
n, err := fmt.Fprint(f, data)
|
||||
if err != nil {
|
||||
panic("fmt.Fprintln: " + err.Error())
|
||||
}
|
||||
if n != len(data) {
|
||||
panic(fmt.Sprintf("Data size mismatch. expected=%d wrote=%d\n", len(data), n))
|
||||
}
|
||||
|
||||
err = f.Close()
|
||||
if err != nil {
|
||||
panic("f.Close: " + err.Error())
|
||||
}
|
||||
|
||||
return f.Name()
|
||||
}
|
||||
|
||||
func testServer() *httptest.Server {
|
||||
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
send := func(data []byte, contentType string) {
|
||||
w.Header().Set("Content-Type", contentType)
|
||||
if _, err := w.Write(data); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
utf8 := []byte("key=äöü")
|
||||
iso88591 := []byte{0x6b, 0x65, 0x79, 0x3d, 0xe4, 0xf6, 0xfc} // key=äöü
|
||||
|
||||
switch r.RequestURI {
|
||||
case "/a":
|
||||
send([]byte("key=value"), "")
|
||||
case "/b":
|
||||
send([]byte("key2=value2"), "")
|
||||
case "/none":
|
||||
send(utf8, "")
|
||||
case "/utf8":
|
||||
send(utf8, "text/plain; charset=utf-8")
|
||||
case "/json":
|
||||
send(utf8, "application/json; charset=utf-8")
|
||||
case "/plain":
|
||||
send(iso88591, "text/plain")
|
||||
case "/latin1":
|
||||
send(iso88591, "text/plain; charset=latin1")
|
||||
case "/iso88591":
|
||||
send(iso88591, "text/plain; charset=iso-8859-1")
|
||||
default:
|
||||
w.WriteHeader(404)
|
||||
}
|
||||
}))
|
||||
}
|
||||
80
vendor/github.com/magiconair/properties/properties.go
generated
vendored
80
vendor/github.com/magiconair/properties/properties.go
generated
vendored
@@ -19,6 +19,8 @@ import (
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
const maxExpansionDepth = 64
|
||||
|
||||
// ErrorHandlerFunc defines the type of function which handles failures
|
||||
// of the MustXXX() functions. An error handler function must exit
|
||||
// the application after handling the error.
|
||||
@@ -92,7 +94,7 @@ func (p *Properties) Get(key string) (value string, ok bool) {
|
||||
return "", false
|
||||
}
|
||||
|
||||
expanded, err := p.expand(v)
|
||||
expanded, err := p.expand(key, v)
|
||||
|
||||
// we guarantee that the expanded value is free of
|
||||
// circular references and malformed expressions
|
||||
@@ -511,6 +513,9 @@ func (p *Properties) Set(key, value string) (prev string, ok bool, err error) {
|
||||
if p.DisableExpansion {
|
||||
prev, ok = p.Get(key)
|
||||
p.m[key] = value
|
||||
if !ok {
|
||||
p.k = append(p.k, key)
|
||||
}
|
||||
return prev, ok, nil
|
||||
}
|
||||
|
||||
@@ -522,7 +527,7 @@ func (p *Properties) Set(key, value string) (prev string, ok bool, err error) {
|
||||
p.m[key] = value
|
||||
|
||||
// now check for a circular reference
|
||||
_, err = p.expand(value)
|
||||
_, err = p.expand(key, value)
|
||||
if err != nil {
|
||||
|
||||
// revert to the previous state
|
||||
@@ -693,56 +698,65 @@ outer:
|
||||
// check expands all values and returns an error if a circular reference or
|
||||
// a malformed expression was found.
|
||||
func (p *Properties) check() error {
|
||||
for _, value := range p.m {
|
||||
if _, err := p.expand(value); err != nil {
|
||||
for key, value := range p.m {
|
||||
if _, err := p.expand(key, value); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Properties) expand(input string) (string, error) {
|
||||
func (p *Properties) expand(key, input string) (string, error) {
|
||||
// no pre/postfix -> nothing to expand
|
||||
if p.Prefix == "" && p.Postfix == "" {
|
||||
return input, nil
|
||||
}
|
||||
|
||||
return expand(input, make(map[string]bool), p.Prefix, p.Postfix, p.m)
|
||||
return expand(input, []string{key}, p.Prefix, p.Postfix, p.m)
|
||||
}
|
||||
|
||||
// expand recursively expands expressions of '(prefix)key(postfix)' to their corresponding values.
|
||||
// The function keeps track of the keys that were already expanded and stops if it
|
||||
// detects a circular reference or a malformed expression of the form '(prefix)key'.
|
||||
func expand(s string, keys map[string]bool, prefix, postfix string, values map[string]string) (string, error) {
|
||||
start := strings.Index(s, prefix)
|
||||
if start == -1 {
|
||||
return s, nil
|
||||
func expand(s string, keys []string, prefix, postfix string, values map[string]string) (string, error) {
|
||||
if len(keys) > maxExpansionDepth {
|
||||
return "", fmt.Errorf("expansion too deep")
|
||||
}
|
||||
|
||||
keyStart := start + len(prefix)
|
||||
keyLen := strings.Index(s[keyStart:], postfix)
|
||||
if keyLen == -1 {
|
||||
return "", fmt.Errorf("malformed expression")
|
||||
for {
|
||||
start := strings.Index(s, prefix)
|
||||
if start == -1 {
|
||||
return s, nil
|
||||
}
|
||||
|
||||
keyStart := start + len(prefix)
|
||||
keyLen := strings.Index(s[keyStart:], postfix)
|
||||
if keyLen == -1 {
|
||||
return "", fmt.Errorf("malformed expression")
|
||||
}
|
||||
|
||||
end := keyStart + keyLen + len(postfix) - 1
|
||||
key := s[keyStart : keyStart+keyLen]
|
||||
|
||||
// fmt.Printf("s:%q pp:%q start:%d end:%d keyStart:%d keyLen:%d key:%q\n", s, prefix + "..." + postfix, start, end, keyStart, keyLen, key)
|
||||
|
||||
for _, k := range keys {
|
||||
if key == k {
|
||||
return "", fmt.Errorf("circular reference")
|
||||
}
|
||||
}
|
||||
|
||||
val, ok := values[key]
|
||||
if !ok {
|
||||
val = os.Getenv(key)
|
||||
}
|
||||
new_val, err := expand(val, append(keys, key), prefix, postfix, values)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
s = s[:start] + new_val + s[end+1:]
|
||||
}
|
||||
|
||||
end := keyStart + keyLen + len(postfix) - 1
|
||||
key := s[keyStart : keyStart+keyLen]
|
||||
|
||||
// fmt.Printf("s:%q pp:%q start:%d end:%d keyStart:%d keyLen:%d key:%q\n", s, prefix + "..." + postfix, start, end, keyStart, keyLen, key)
|
||||
|
||||
if _, ok := keys[key]; ok {
|
||||
return "", fmt.Errorf("circular reference")
|
||||
}
|
||||
|
||||
val, ok := values[key]
|
||||
if !ok {
|
||||
val = os.Getenv(key)
|
||||
}
|
||||
|
||||
// remember that we've seen the key
|
||||
keys[key] = true
|
||||
|
||||
return expand(s[:start]+val+s[end+1:], keys, prefix, postfix, values)
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// encode encodes a UTF-8 string to ISO-8859-1 and escapes some characters.
|
||||
|
||||
934
vendor/github.com/magiconair/properties/properties_test.go
generated
vendored
934
vendor/github.com/magiconair/properties/properties_test.go
generated
vendored
@@ -1,934 +0,0 @@
|
||||
// Copyright 2017 Frank Schroeder. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package properties
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/magiconair/properties/assert"
|
||||
)
|
||||
|
||||
var verbose = flag.Bool("verbose", false, "Verbose output")
|
||||
|
||||
func init() {
|
||||
ErrorHandler = PanicHandler
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// define test cases in the form of
|
||||
// {"input", "key1", "value1", "key2", "value2", ...}
|
||||
var complexTests = [][]string{
|
||||
// whitespace prefix
|
||||
{" key=value", "key", "value"}, // SPACE prefix
|
||||
{"\fkey=value", "key", "value"}, // FF prefix
|
||||
{"\tkey=value", "key", "value"}, // TAB prefix
|
||||
{" \f\tkey=value", "key", "value"}, // mix prefix
|
||||
|
||||
// multiple keys
|
||||
{"key1=value1\nkey2=value2\n", "key1", "value1", "key2", "value2"},
|
||||
{"key1=value1\rkey2=value2\r", "key1", "value1", "key2", "value2"},
|
||||
{"key1=value1\r\nkey2=value2\r\n", "key1", "value1", "key2", "value2"},
|
||||
|
||||
// blank lines
|
||||
{"\nkey=value\n", "key", "value"},
|
||||
{"\rkey=value\r", "key", "value"},
|
||||
{"\r\nkey=value\r\n", "key", "value"},
|
||||
|
||||
// escaped chars in key
|
||||
{"k\\ ey = value", "k ey", "value"},
|
||||
{"k\\:ey = value", "k:ey", "value"},
|
||||
{"k\\=ey = value", "k=ey", "value"},
|
||||
{"k\\fey = value", "k\fey", "value"},
|
||||
{"k\\ney = value", "k\ney", "value"},
|
||||
{"k\\rey = value", "k\rey", "value"},
|
||||
{"k\\tey = value", "k\tey", "value"},
|
||||
|
||||
// escaped chars in value
|
||||
{"key = v\\ alue", "key", "v alue"},
|
||||
{"key = v\\:alue", "key", "v:alue"},
|
||||
{"key = v\\=alue", "key", "v=alue"},
|
||||
{"key = v\\falue", "key", "v\falue"},
|
||||
{"key = v\\nalue", "key", "v\nalue"},
|
||||
{"key = v\\ralue", "key", "v\ralue"},
|
||||
{"key = v\\talue", "key", "v\talue"},
|
||||
|
||||
// silently dropped escape character
|
||||
{"k\\zey = value", "kzey", "value"},
|
||||
{"key = v\\zalue", "key", "vzalue"},
|
||||
|
||||
// unicode literals
|
||||
{"key\\u2318 = value", "key⌘", "value"},
|
||||
{"k\\u2318ey = value", "k⌘ey", "value"},
|
||||
{"key = value\\u2318", "key", "value⌘"},
|
||||
{"key = valu\\u2318e", "key", "valu⌘e"},
|
||||
|
||||
// multiline values
|
||||
{"key = valueA,\\\n valueB", "key", "valueA,valueB"}, // SPACE indent
|
||||
{"key = valueA,\\\n\f\f\fvalueB", "key", "valueA,valueB"}, // FF indent
|
||||
{"key = valueA,\\\n\t\t\tvalueB", "key", "valueA,valueB"}, // TAB indent
|
||||
{"key = valueA,\\\n \f\tvalueB", "key", "valueA,valueB"}, // mix indent
|
||||
|
||||
// comments
|
||||
{"# this is a comment\n! and so is this\nkey1=value1\nkey#2=value#2\n\nkey!3=value!3\n# and another one\n! and the final one", "key1", "value1", "key#2", "value#2", "key!3", "value!3"},
|
||||
|
||||
// expansion tests
|
||||
{"key=value\nkey2=${key}", "key", "value", "key2", "value"},
|
||||
{"key=value\nkey2=aa${key}", "key", "value", "key2", "aavalue"},
|
||||
{"key=value\nkey2=${key}bb", "key", "value", "key2", "valuebb"},
|
||||
{"key=value\nkey2=aa${key}bb", "key", "value", "key2", "aavaluebb"},
|
||||
{"key=value\nkey2=${key}\nkey3=${key2}", "key", "value", "key2", "value", "key3", "value"},
|
||||
{"key=${USER}", "key", os.Getenv("USER")},
|
||||
{"key=${USER}\nUSER=value", "key", "value", "USER", "value"},
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
var commentTests = []struct {
|
||||
input, key, value string
|
||||
comments []string
|
||||
}{
|
||||
{"key=value", "key", "value", nil},
|
||||
{"#\nkey=value", "key", "value", []string{""}},
|
||||
{"#comment\nkey=value", "key", "value", []string{"comment"}},
|
||||
{"# comment\nkey=value", "key", "value", []string{"comment"}},
|
||||
{"# comment\nkey=value", "key", "value", []string{"comment"}},
|
||||
{"# comment\n\nkey=value", "key", "value", []string{"comment"}},
|
||||
{"# comment1\n# comment2\nkey=value", "key", "value", []string{"comment1", "comment2"}},
|
||||
{"# comment1\n\n# comment2\n\nkey=value", "key", "value", []string{"comment1", "comment2"}},
|
||||
{"!comment\nkey=value", "key", "value", []string{"comment"}},
|
||||
{"! comment\nkey=value", "key", "value", []string{"comment"}},
|
||||
{"! comment\nkey=value", "key", "value", []string{"comment"}},
|
||||
{"! comment\n\nkey=value", "key", "value", []string{"comment"}},
|
||||
{"! comment1\n! comment2\nkey=value", "key", "value", []string{"comment1", "comment2"}},
|
||||
{"! comment1\n\n! comment2\n\nkey=value", "key", "value", []string{"comment1", "comment2"}},
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
var errorTests = []struct {
|
||||
input, msg string
|
||||
}{
|
||||
// unicode literals
|
||||
{"key\\u1 = value", "invalid unicode literal"},
|
||||
{"key\\u12 = value", "invalid unicode literal"},
|
||||
{"key\\u123 = value", "invalid unicode literal"},
|
||||
{"key\\u123g = value", "invalid unicode literal"},
|
||||
{"key\\u123", "invalid unicode literal"},
|
||||
|
||||
// circular references
|
||||
{"key=${key}", "circular reference"},
|
||||
{"key1=${key2}\nkey2=${key1}", "circular reference"},
|
||||
|
||||
// malformed expressions
|
||||
{"key=${ke", "malformed expression"},
|
||||
{"key=valu${ke", "malformed expression"},
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
var writeTests = []struct {
|
||||
input, output, encoding string
|
||||
}{
|
||||
// ISO-8859-1 tests
|
||||
{"key = value", "key = value\n", "ISO-8859-1"},
|
||||
{"key = value \\\n continued", "key = value continued\n", "ISO-8859-1"},
|
||||
{"key⌘ = value", "key\\u2318 = value\n", "ISO-8859-1"},
|
||||
{"ke\\ \\:y = value", "ke\\ \\:y = value\n", "ISO-8859-1"},
|
||||
|
||||
// UTF-8 tests
|
||||
{"key = value", "key = value\n", "UTF-8"},
|
||||
{"key = value \\\n continued", "key = value continued\n", "UTF-8"},
|
||||
{"key⌘ = value⌘", "key⌘ = value⌘\n", "UTF-8"},
|
||||
{"ke\\ \\:y = value", "ke\\ \\:y = value\n", "UTF-8"},
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
var writeCommentTests = []struct {
|
||||
input, output, encoding string
|
||||
}{
|
||||
// ISO-8859-1 tests
|
||||
{"key = value", "key = value\n", "ISO-8859-1"},
|
||||
{"#\nkey = value", "key = value\n", "ISO-8859-1"},
|
||||
{"#\n#\n#\nkey = value", "key = value\n", "ISO-8859-1"},
|
||||
{"# comment\nkey = value", "# comment\nkey = value\n", "ISO-8859-1"},
|
||||
{"\n# comment\nkey = value", "# comment\nkey = value\n", "ISO-8859-1"},
|
||||
{"# comment\n\nkey = value", "# comment\nkey = value\n", "ISO-8859-1"},
|
||||
{"# comment1\n# comment2\nkey = value", "# comment1\n# comment2\nkey = value\n", "ISO-8859-1"},
|
||||
{"#comment1\nkey1 = value1\n#comment2\nkey2 = value2", "# comment1\nkey1 = value1\n\n# comment2\nkey2 = value2\n", "ISO-8859-1"},
|
||||
|
||||
// UTF-8 tests
|
||||
{"key = value", "key = value\n", "UTF-8"},
|
||||
{"# comment⌘\nkey = value⌘", "# comment⌘\nkey = value⌘\n", "UTF-8"},
|
||||
{"\n# comment⌘\nkey = value⌘", "# comment⌘\nkey = value⌘\n", "UTF-8"},
|
||||
{"# comment⌘\n\nkey = value⌘", "# comment⌘\nkey = value⌘\n", "UTF-8"},
|
||||
{"# comment1⌘\n# comment2⌘\nkey = value⌘", "# comment1⌘\n# comment2⌘\nkey = value⌘\n", "UTF-8"},
|
||||
{"#comment1⌘\nkey1 = value1⌘\n#comment2⌘\nkey2 = value2⌘", "# comment1⌘\nkey1 = value1⌘\n\n# comment2⌘\nkey2 = value2⌘\n", "UTF-8"},
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
var boolTests = []struct {
|
||||
input, key string
|
||||
def, value bool
|
||||
}{
|
||||
// valid values for TRUE
|
||||
{"key = 1", "key", false, true},
|
||||
{"key = on", "key", false, true},
|
||||
{"key = On", "key", false, true},
|
||||
{"key = ON", "key", false, true},
|
||||
{"key = true", "key", false, true},
|
||||
{"key = True", "key", false, true},
|
||||
{"key = TRUE", "key", false, true},
|
||||
{"key = yes", "key", false, true},
|
||||
{"key = Yes", "key", false, true},
|
||||
{"key = YES", "key", false, true},
|
||||
|
||||
// valid values for FALSE (all other)
|
||||
{"key = 0", "key", true, false},
|
||||
{"key = off", "key", true, false},
|
||||
{"key = false", "key", true, false},
|
||||
{"key = no", "key", true, false},
|
||||
|
||||
// non existent key
|
||||
{"key = true", "key2", false, false},
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
var durationTests = []struct {
|
||||
input, key string
|
||||
def, value time.Duration
|
||||
}{
|
||||
// valid values
|
||||
{"key = 1", "key", 999, 1},
|
||||
{"key = 0", "key", 999, 0},
|
||||
{"key = -1", "key", 999, -1},
|
||||
{"key = 0123", "key", 999, 123},
|
||||
|
||||
// invalid values
|
||||
{"key = 0xff", "key", 999, 999},
|
||||
{"key = 1.0", "key", 999, 999},
|
||||
{"key = a", "key", 999, 999},
|
||||
|
||||
// non existent key
|
||||
{"key = 1", "key2", 999, 999},
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
var parsedDurationTests = []struct {
|
||||
input, key string
|
||||
def, value time.Duration
|
||||
}{
|
||||
// valid values
|
||||
{"key = -1ns", "key", 999, -1 * time.Nanosecond},
|
||||
{"key = 300ms", "key", 999, 300 * time.Millisecond},
|
||||
{"key = 5s", "key", 999, 5 * time.Second},
|
||||
{"key = 3h", "key", 999, 3 * time.Hour},
|
||||
{"key = 2h45m", "key", 999, 2*time.Hour + 45*time.Minute},
|
||||
|
||||
// invalid values
|
||||
{"key = 0xff", "key", 999, 999},
|
||||
{"key = 1.0", "key", 999, 999},
|
||||
{"key = a", "key", 999, 999},
|
||||
{"key = 1", "key", 999, 999},
|
||||
{"key = 0", "key", 999, 0},
|
||||
|
||||
// non existent key
|
||||
{"key = 1", "key2", 999, 999},
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
var floatTests = []struct {
|
||||
input, key string
|
||||
def, value float64
|
||||
}{
|
||||
// valid values
|
||||
{"key = 1.0", "key", 999, 1.0},
|
||||
{"key = 0.0", "key", 999, 0.0},
|
||||
{"key = -1.0", "key", 999, -1.0},
|
||||
{"key = 1", "key", 999, 1},
|
||||
{"key = 0", "key", 999, 0},
|
||||
{"key = -1", "key", 999, -1},
|
||||
{"key = 0123", "key", 999, 123},
|
||||
|
||||
// invalid values
|
||||
{"key = 0xff", "key", 999, 999},
|
||||
{"key = a", "key", 999, 999},
|
||||
|
||||
// non existent key
|
||||
{"key = 1", "key2", 999, 999},
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
var int64Tests = []struct {
|
||||
input, key string
|
||||
def, value int64
|
||||
}{
|
||||
// valid values
|
||||
{"key = 1", "key", 999, 1},
|
||||
{"key = 0", "key", 999, 0},
|
||||
{"key = -1", "key", 999, -1},
|
||||
{"key = 0123", "key", 999, 123},
|
||||
|
||||
// invalid values
|
||||
{"key = 0xff", "key", 999, 999},
|
||||
{"key = 1.0", "key", 999, 999},
|
||||
{"key = a", "key", 999, 999},
|
||||
|
||||
// non existent key
|
||||
{"key = 1", "key2", 999, 999},
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
var uint64Tests = []struct {
|
||||
input, key string
|
||||
def, value uint64
|
||||
}{
|
||||
// valid values
|
||||
{"key = 1", "key", 999, 1},
|
||||
{"key = 0", "key", 999, 0},
|
||||
{"key = 0123", "key", 999, 123},
|
||||
|
||||
// invalid values
|
||||
{"key = -1", "key", 999, 999},
|
||||
{"key = 0xff", "key", 999, 999},
|
||||
{"key = 1.0", "key", 999, 999},
|
||||
{"key = a", "key", 999, 999},
|
||||
|
||||
// non existent key
|
||||
{"key = 1", "key2", 999, 999},
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
var stringTests = []struct {
|
||||
input, key string
|
||||
def, value string
|
||||
}{
|
||||
// valid values
|
||||
{"key = abc", "key", "def", "abc"},
|
||||
|
||||
// non existent key
|
||||
{"key = abc", "key2", "def", "def"},
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
var keysTests = []struct {
|
||||
input string
|
||||
keys []string
|
||||
}{
|
||||
{"", []string{}},
|
||||
{"key = abc", []string{"key"}},
|
||||
{"key = abc\nkey2=def", []string{"key", "key2"}},
|
||||
{"key2 = abc\nkey=def", []string{"key2", "key"}},
|
||||
{"key = abc\nkey=def", []string{"key"}},
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
var filterTests = []struct {
|
||||
input string
|
||||
pattern string
|
||||
keys []string
|
||||
err string
|
||||
}{
|
||||
{"", "", []string{}, ""},
|
||||
{"", "abc", []string{}, ""},
|
||||
{"key=value", "", []string{"key"}, ""},
|
||||
{"key=value", "key=", []string{}, ""},
|
||||
{"key=value\nfoo=bar", "", []string{"foo", "key"}, ""},
|
||||
{"key=value\nfoo=bar", "f", []string{"foo"}, ""},
|
||||
{"key=value\nfoo=bar", "fo", []string{"foo"}, ""},
|
||||
{"key=value\nfoo=bar", "foo", []string{"foo"}, ""},
|
||||
{"key=value\nfoo=bar", "fooo", []string{}, ""},
|
||||
{"key=value\nkey2=value2\nfoo=bar", "ey", []string{"key", "key2"}, ""},
|
||||
{"key=value\nkey2=value2\nfoo=bar", "key", []string{"key", "key2"}, ""},
|
||||
{"key=value\nkey2=value2\nfoo=bar", "^key", []string{"key", "key2"}, ""},
|
||||
{"key=value\nkey2=value2\nfoo=bar", "^(key|foo)", []string{"foo", "key", "key2"}, ""},
|
||||
{"key=value\nkey2=value2\nfoo=bar", "[ abc", nil, "error parsing regexp.*"},
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
var filterPrefixTests = []struct {
|
||||
input string
|
||||
prefix string
|
||||
keys []string
|
||||
}{
|
||||
{"", "", []string{}},
|
||||
{"", "abc", []string{}},
|
||||
{"key=value", "", []string{"key"}},
|
||||
{"key=value", "key=", []string{}},
|
||||
{"key=value\nfoo=bar", "", []string{"foo", "key"}},
|
||||
{"key=value\nfoo=bar", "f", []string{"foo"}},
|
||||
{"key=value\nfoo=bar", "fo", []string{"foo"}},
|
||||
{"key=value\nfoo=bar", "foo", []string{"foo"}},
|
||||
{"key=value\nfoo=bar", "fooo", []string{}},
|
||||
{"key=value\nkey2=value2\nfoo=bar", "key", []string{"key", "key2"}},
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
var filterStripPrefixTests = []struct {
|
||||
input string
|
||||
prefix string
|
||||
keys []string
|
||||
}{
|
||||
{"", "", []string{}},
|
||||
{"", "abc", []string{}},
|
||||
{"key=value", "", []string{"key"}},
|
||||
{"key=value", "key=", []string{}},
|
||||
{"key=value\nfoo=bar", "", []string{"foo", "key"}},
|
||||
{"key=value\nfoo=bar", "f", []string{"foo"}},
|
||||
{"key=value\nfoo=bar", "fo", []string{"foo"}},
|
||||
{"key=value\nfoo=bar", "foo", []string{"foo"}},
|
||||
{"key=value\nfoo=bar", "fooo", []string{}},
|
||||
{"key=value\nkey2=value2\nfoo=bar", "key", []string{"key", "key2"}},
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
var setTests = []struct {
|
||||
input string
|
||||
key, value string
|
||||
prev string
|
||||
ok bool
|
||||
err string
|
||||
keys []string
|
||||
}{
|
||||
{"", "", "", "", false, "", []string{}},
|
||||
{"", "key", "value", "", false, "", []string{"key"}},
|
||||
{"key=value", "key2", "value2", "", false, "", []string{"key", "key2"}},
|
||||
{"key=value", "abc", "value3", "", false, "", []string{"key", "abc"}},
|
||||
{"key=value", "key", "value3", "value", true, "", []string{"key"}},
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// TestBasic tests basic single key/value combinations with all possible
|
||||
// whitespace, delimiter and newline permutations.
|
||||
func TestBasic(t *testing.T) {
|
||||
testWhitespaceAndDelimiterCombinations(t, "key", "")
|
||||
testWhitespaceAndDelimiterCombinations(t, "key", "value")
|
||||
testWhitespaceAndDelimiterCombinations(t, "key", "value ")
|
||||
}
|
||||
|
||||
func TestComplex(t *testing.T) {
|
||||
for _, test := range complexTests {
|
||||
testKeyValue(t, test[0], test[1:]...)
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrors(t *testing.T) {
|
||||
for _, test := range errorTests {
|
||||
_, err := Load([]byte(test.input), ISO_8859_1)
|
||||
assert.Equal(t, err != nil, true, "want error")
|
||||
assert.Equal(t, strings.Contains(err.Error(), test.msg), true)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDisableExpansion(t *testing.T) {
|
||||
input := "key=value\nkey2=${key}"
|
||||
p := mustParse(t, input)
|
||||
p.DisableExpansion = true
|
||||
assert.Equal(t, p.MustGet("key"), "value")
|
||||
assert.Equal(t, p.MustGet("key2"), "${key}")
|
||||
|
||||
// with expansion disabled we can introduce circular references
|
||||
p.MustSet("keyA", "${keyB}")
|
||||
p.MustSet("keyB", "${keyA}")
|
||||
assert.Equal(t, p.MustGet("keyA"), "${keyB}")
|
||||
assert.Equal(t, p.MustGet("keyB"), "${keyA}")
|
||||
}
|
||||
|
||||
func TestMustGet(t *testing.T) {
|
||||
input := "key = value\nkey2 = ghi"
|
||||
p := mustParse(t, input)
|
||||
assert.Equal(t, p.MustGet("key"), "value")
|
||||
assert.Panic(t, func() { p.MustGet("invalid") }, "unknown property: invalid")
|
||||
}
|
||||
|
||||
func TestGetBool(t *testing.T) {
|
||||
for _, test := range boolTests {
|
||||
p := mustParse(t, test.input)
|
||||
assert.Equal(t, p.Len(), 1)
|
||||
assert.Equal(t, p.GetBool(test.key, test.def), test.value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMustGetBool(t *testing.T) {
|
||||
input := "key = true\nkey2 = ghi"
|
||||
p := mustParse(t, input)
|
||||
assert.Equal(t, p.MustGetBool("key"), true)
|
||||
assert.Panic(t, func() { p.MustGetBool("invalid") }, "unknown property: invalid")
|
||||
}
|
||||
|
||||
func TestGetDuration(t *testing.T) {
|
||||
for _, test := range durationTests {
|
||||
p := mustParse(t, test.input)
|
||||
assert.Equal(t, p.Len(), 1)
|
||||
assert.Equal(t, p.GetDuration(test.key, test.def), test.value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMustGetDuration(t *testing.T) {
|
||||
input := "key = 123\nkey2 = ghi"
|
||||
p := mustParse(t, input)
|
||||
assert.Equal(t, p.MustGetDuration("key"), time.Duration(123))
|
||||
assert.Panic(t, func() { p.MustGetDuration("key2") }, "strconv.ParseInt: parsing.*")
|
||||
assert.Panic(t, func() { p.MustGetDuration("invalid") }, "unknown property: invalid")
|
||||
}
|
||||
|
||||
func TestGetParsedDuration(t *testing.T) {
|
||||
for _, test := range parsedDurationTests {
|
||||
p := mustParse(t, test.input)
|
||||
assert.Equal(t, p.Len(), 1)
|
||||
assert.Equal(t, p.GetParsedDuration(test.key, test.def), test.value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMustGetParsedDuration(t *testing.T) {
|
||||
input := "key = 123ms\nkey2 = ghi"
|
||||
p := mustParse(t, input)
|
||||
assert.Equal(t, p.MustGetParsedDuration("key"), 123*time.Millisecond)
|
||||
assert.Panic(t, func() { p.MustGetParsedDuration("key2") }, "time: invalid duration ghi")
|
||||
assert.Panic(t, func() { p.MustGetParsedDuration("invalid") }, "unknown property: invalid")
|
||||
}
|
||||
|
||||
func TestGetFloat64(t *testing.T) {
|
||||
for _, test := range floatTests {
|
||||
p := mustParse(t, test.input)
|
||||
assert.Equal(t, p.Len(), 1)
|
||||
assert.Equal(t, p.GetFloat64(test.key, test.def), test.value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMustGetFloat64(t *testing.T) {
|
||||
input := "key = 123\nkey2 = ghi"
|
||||
p := mustParse(t, input)
|
||||
assert.Equal(t, p.MustGetFloat64("key"), float64(123))
|
||||
assert.Panic(t, func() { p.MustGetFloat64("key2") }, "strconv.ParseFloat: parsing.*")
|
||||
assert.Panic(t, func() { p.MustGetFloat64("invalid") }, "unknown property: invalid")
|
||||
}
|
||||
|
||||
func TestGetInt(t *testing.T) {
|
||||
for _, test := range int64Tests {
|
||||
p := mustParse(t, test.input)
|
||||
assert.Equal(t, p.Len(), 1)
|
||||
assert.Equal(t, p.GetInt(test.key, int(test.def)), int(test.value))
|
||||
}
|
||||
}
|
||||
|
||||
func TestMustGetInt(t *testing.T) {
|
||||
input := "key = 123\nkey2 = ghi"
|
||||
p := mustParse(t, input)
|
||||
assert.Equal(t, p.MustGetInt("key"), int(123))
|
||||
assert.Panic(t, func() { p.MustGetInt("key2") }, "strconv.ParseInt: parsing.*")
|
||||
assert.Panic(t, func() { p.MustGetInt("invalid") }, "unknown property: invalid")
|
||||
}
|
||||
|
||||
func TestGetInt64(t *testing.T) {
|
||||
for _, test := range int64Tests {
|
||||
p := mustParse(t, test.input)
|
||||
assert.Equal(t, p.Len(), 1)
|
||||
assert.Equal(t, p.GetInt64(test.key, test.def), test.value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMustGetInt64(t *testing.T) {
|
||||
input := "key = 123\nkey2 = ghi"
|
||||
p := mustParse(t, input)
|
||||
assert.Equal(t, p.MustGetInt64("key"), int64(123))
|
||||
assert.Panic(t, func() { p.MustGetInt64("key2") }, "strconv.ParseInt: parsing.*")
|
||||
assert.Panic(t, func() { p.MustGetInt64("invalid") }, "unknown property: invalid")
|
||||
}
|
||||
|
||||
func TestGetUint(t *testing.T) {
|
||||
for _, test := range uint64Tests {
|
||||
p := mustParse(t, test.input)
|
||||
assert.Equal(t, p.Len(), 1)
|
||||
assert.Equal(t, p.GetUint(test.key, uint(test.def)), uint(test.value))
|
||||
}
|
||||
}
|
||||
|
||||
func TestMustGetUint(t *testing.T) {
|
||||
input := "key = 123\nkey2 = ghi"
|
||||
p := mustParse(t, input)
|
||||
assert.Equal(t, p.MustGetUint("key"), uint(123))
|
||||
assert.Panic(t, func() { p.MustGetUint64("key2") }, "strconv.ParseUint: parsing.*")
|
||||
assert.Panic(t, func() { p.MustGetUint64("invalid") }, "unknown property: invalid")
|
||||
}
|
||||
|
||||
func TestGetUint64(t *testing.T) {
|
||||
for _, test := range uint64Tests {
|
||||
p := mustParse(t, test.input)
|
||||
assert.Equal(t, p.Len(), 1)
|
||||
assert.Equal(t, p.GetUint64(test.key, test.def), test.value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMustGetUint64(t *testing.T) {
|
||||
input := "key = 123\nkey2 = ghi"
|
||||
p := mustParse(t, input)
|
||||
assert.Equal(t, p.MustGetUint64("key"), uint64(123))
|
||||
assert.Panic(t, func() { p.MustGetUint64("key2") }, "strconv.ParseUint: parsing.*")
|
||||
assert.Panic(t, func() { p.MustGetUint64("invalid") }, "unknown property: invalid")
|
||||
}
|
||||
|
||||
func TestGetString(t *testing.T) {
|
||||
for _, test := range stringTests {
|
||||
p := mustParse(t, test.input)
|
||||
assert.Equal(t, p.Len(), 1)
|
||||
assert.Equal(t, p.GetString(test.key, test.def), test.value)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMustGetString(t *testing.T) {
|
||||
input := `key = value`
|
||||
p := mustParse(t, input)
|
||||
assert.Equal(t, p.MustGetString("key"), "value")
|
||||
assert.Panic(t, func() { p.MustGetString("invalid") }, "unknown property: invalid")
|
||||
}
|
||||
|
||||
func TestComment(t *testing.T) {
|
||||
for _, test := range commentTests {
|
||||
p := mustParse(t, test.input)
|
||||
assert.Equal(t, p.MustGetString(test.key), test.value)
|
||||
assert.Equal(t, p.GetComments(test.key), test.comments)
|
||||
if test.comments != nil {
|
||||
assert.Equal(t, p.GetComment(test.key), test.comments[len(test.comments)-1])
|
||||
} else {
|
||||
assert.Equal(t, p.GetComment(test.key), "")
|
||||
}
|
||||
|
||||
// test setting comments
|
||||
if len(test.comments) > 0 {
|
||||
// set single comment
|
||||
p.ClearComments()
|
||||
assert.Equal(t, len(p.c), 0)
|
||||
p.SetComment(test.key, test.comments[0])
|
||||
assert.Equal(t, p.GetComment(test.key), test.comments[0])
|
||||
|
||||
// set multiple comments
|
||||
p.ClearComments()
|
||||
assert.Equal(t, len(p.c), 0)
|
||||
p.SetComments(test.key, test.comments)
|
||||
assert.Equal(t, p.GetComments(test.key), test.comments)
|
||||
|
||||
// clear comments for a key
|
||||
p.SetComments(test.key, nil)
|
||||
assert.Equal(t, p.GetComment(test.key), "")
|
||||
assert.Equal(t, p.GetComments(test.key), ([]string)(nil))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilter(t *testing.T) {
|
||||
for _, test := range filterTests {
|
||||
p := mustParse(t, test.input)
|
||||
pp, err := p.Filter(test.pattern)
|
||||
if err != nil {
|
||||
assert.Matches(t, err.Error(), test.err)
|
||||
continue
|
||||
}
|
||||
assert.Equal(t, pp != nil, true, "want properties")
|
||||
assert.Equal(t, pp.Len(), len(test.keys))
|
||||
for _, key := range test.keys {
|
||||
v1, ok1 := p.Get(key)
|
||||
v2, ok2 := pp.Get(key)
|
||||
assert.Equal(t, ok1, true)
|
||||
assert.Equal(t, ok2, true)
|
||||
assert.Equal(t, v1, v2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterPrefix(t *testing.T) {
|
||||
for _, test := range filterPrefixTests {
|
||||
p := mustParse(t, test.input)
|
||||
pp := p.FilterPrefix(test.prefix)
|
||||
assert.Equal(t, pp != nil, true, "want properties")
|
||||
assert.Equal(t, pp.Len(), len(test.keys))
|
||||
for _, key := range test.keys {
|
||||
v1, ok1 := p.Get(key)
|
||||
v2, ok2 := pp.Get(key)
|
||||
assert.Equal(t, ok1, true)
|
||||
assert.Equal(t, ok2, true)
|
||||
assert.Equal(t, v1, v2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterStripPrefix(t *testing.T) {
|
||||
for _, test := range filterStripPrefixTests {
|
||||
p := mustParse(t, test.input)
|
||||
pp := p.FilterPrefix(test.prefix)
|
||||
assert.Equal(t, pp != nil, true, "want properties")
|
||||
assert.Equal(t, pp.Len(), len(test.keys))
|
||||
for _, key := range test.keys {
|
||||
v1, ok1 := p.Get(key)
|
||||
v2, ok2 := pp.Get(key)
|
||||
assert.Equal(t, ok1, true)
|
||||
assert.Equal(t, ok2, true)
|
||||
assert.Equal(t, v1, v2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestKeys(t *testing.T) {
|
||||
for _, test := range keysTests {
|
||||
p := mustParse(t, test.input)
|
||||
assert.Equal(t, p.Len(), len(test.keys))
|
||||
assert.Equal(t, len(p.Keys()), len(test.keys))
|
||||
assert.Equal(t, p.Keys(), test.keys)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSet(t *testing.T) {
|
||||
for _, test := range setTests {
|
||||
p := mustParse(t, test.input)
|
||||
prev, ok, err := p.Set(test.key, test.value)
|
||||
if test.err != "" {
|
||||
assert.Matches(t, err.Error(), test.err)
|
||||
continue
|
||||
}
|
||||
|
||||
assert.Equal(t, err, nil)
|
||||
assert.Equal(t, ok, test.ok)
|
||||
if ok {
|
||||
assert.Equal(t, prev, test.prev)
|
||||
}
|
||||
assert.Equal(t, p.Keys(), test.keys)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetValue(t *testing.T) {
|
||||
tests := []interface{}{
|
||||
true, false,
|
||||
int8(123), int16(123), int32(123), int64(123), int(123),
|
||||
uint8(123), uint16(123), uint32(123), uint64(123), uint(123),
|
||||
float32(1.23), float64(1.23),
|
||||
"abc",
|
||||
}
|
||||
|
||||
for _, v := range tests {
|
||||
p := NewProperties()
|
||||
err := p.SetValue("x", v)
|
||||
assert.Equal(t, err, nil)
|
||||
assert.Equal(t, p.GetString("x", ""), fmt.Sprintf("%v", v))
|
||||
}
|
||||
}
|
||||
|
||||
func TestMustSet(t *testing.T) {
|
||||
input := "key=${key}"
|
||||
p := mustParse(t, input)
|
||||
assert.Panic(t, func() { p.MustSet("key", "${key}") }, "circular reference .*")
|
||||
}
|
||||
|
||||
func TestWrite(t *testing.T) {
|
||||
for _, test := range writeTests {
|
||||
p, err := parse(test.input)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
var n int
|
||||
switch test.encoding {
|
||||
case "UTF-8":
|
||||
n, err = p.Write(buf, UTF8)
|
||||
case "ISO-8859-1":
|
||||
n, err = p.Write(buf, ISO_8859_1)
|
||||
}
|
||||
assert.Equal(t, err, nil)
|
||||
s := string(buf.Bytes())
|
||||
assert.Equal(t, n, len(test.output), fmt.Sprintf("input=%q expected=%q obtained=%q", test.input, test.output, s))
|
||||
assert.Equal(t, s, test.output, fmt.Sprintf("input=%q expected=%q obtained=%q", test.input, test.output, s))
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteComment(t *testing.T) {
|
||||
for _, test := range writeCommentTests {
|
||||
p, err := parse(test.input)
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
var n int
|
||||
switch test.encoding {
|
||||
case "UTF-8":
|
||||
n, err = p.WriteComment(buf, "# ", UTF8)
|
||||
case "ISO-8859-1":
|
||||
n, err = p.WriteComment(buf, "# ", ISO_8859_1)
|
||||
}
|
||||
assert.Equal(t, err, nil)
|
||||
s := string(buf.Bytes())
|
||||
assert.Equal(t, n, len(test.output), fmt.Sprintf("input=%q expected=%q obtained=%q", test.input, test.output, s))
|
||||
assert.Equal(t, s, test.output, fmt.Sprintf("input=%q expected=%q obtained=%q", test.input, test.output, s))
|
||||
}
|
||||
}
|
||||
|
||||
func TestCustomExpansionExpression(t *testing.T) {
|
||||
testKeyValuePrePostfix(t, "*[", "]*", "key=value\nkey2=*[key]*", "key", "value", "key2", "value")
|
||||
}
|
||||
|
||||
func TestPanicOn32BitIntOverflow(t *testing.T) {
|
||||
is32Bit = true
|
||||
var min, max int64 = math.MinInt32 - 1, math.MaxInt32 + 1
|
||||
input := fmt.Sprintf("min=%d\nmax=%d", min, max)
|
||||
p := mustParse(t, input)
|
||||
assert.Equal(t, p.MustGetInt64("min"), min)
|
||||
assert.Equal(t, p.MustGetInt64("max"), max)
|
||||
assert.Panic(t, func() { p.MustGetInt("min") }, ".* out of range")
|
||||
assert.Panic(t, func() { p.MustGetInt("max") }, ".* out of range")
|
||||
}
|
||||
|
||||
func TestPanicOn32BitUintOverflow(t *testing.T) {
|
||||
is32Bit = true
|
||||
var max uint64 = math.MaxUint32 + 1
|
||||
input := fmt.Sprintf("max=%d", max)
|
||||
p := mustParse(t, input)
|
||||
assert.Equal(t, p.MustGetUint64("max"), max)
|
||||
assert.Panic(t, func() { p.MustGetUint("max") }, ".* out of range")
|
||||
}
|
||||
|
||||
func TestDeleteKey(t *testing.T) {
|
||||
input := "#comments should also be gone\nkey=to-be-deleted\nsecond=key"
|
||||
p := mustParse(t, input)
|
||||
assert.Equal(t, len(p.m), 2)
|
||||
assert.Equal(t, len(p.c), 1)
|
||||
assert.Equal(t, len(p.k), 2)
|
||||
p.Delete("key")
|
||||
assert.Equal(t, len(p.m), 1)
|
||||
assert.Equal(t, len(p.c), 0)
|
||||
assert.Equal(t, len(p.k), 1)
|
||||
assert.Equal(t, p.k[0], "second")
|
||||
assert.Equal(t, p.m["second"], "key")
|
||||
}
|
||||
|
||||
func TestDeleteUnknownKey(t *testing.T) {
|
||||
input := "#comments should also be gone\nkey=to-be-deleted"
|
||||
p := mustParse(t, input)
|
||||
assert.Equal(t, len(p.m), 1)
|
||||
assert.Equal(t, len(p.c), 1)
|
||||
assert.Equal(t, len(p.k), 1)
|
||||
p.Delete("wrong-key")
|
||||
assert.Equal(t, len(p.m), 1)
|
||||
assert.Equal(t, len(p.c), 1)
|
||||
assert.Equal(t, len(p.k), 1)
|
||||
}
|
||||
|
||||
func TestMerge(t *testing.T) {
|
||||
input1 := "#comment\nkey=value\nkey2=value2"
|
||||
input2 := "#another comment\nkey=another value\nkey3=value3"
|
||||
p1 := mustParse(t, input1)
|
||||
p2 := mustParse(t, input2)
|
||||
p1.Merge(p2)
|
||||
assert.Equal(t, len(p1.m), 3)
|
||||
assert.Equal(t, len(p1.c), 1)
|
||||
assert.Equal(t, len(p1.k), 3)
|
||||
assert.Equal(t, p1.MustGet("key"), "another value")
|
||||
assert.Equal(t, p1.GetComment("key"), "another comment")
|
||||
}
|
||||
|
||||
func TestMap(t *testing.T) {
|
||||
input := "key=value\nabc=def"
|
||||
p := mustParse(t, input)
|
||||
m := map[string]string{"key": "value", "abc": "def"}
|
||||
assert.Equal(t, p.Map(), m)
|
||||
}
|
||||
|
||||
func TestFilterFunc(t *testing.T) {
|
||||
input := "key=value\nabc=def"
|
||||
p := mustParse(t, input)
|
||||
pp := p.FilterFunc(func(k, v string) bool {
|
||||
return k != "abc"
|
||||
})
|
||||
m := map[string]string{"key": "value"}
|
||||
assert.Equal(t, pp.Map(), m)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// tests all combinations of delimiters, leading and/or trailing whitespace and newlines.
|
||||
func testWhitespaceAndDelimiterCombinations(t *testing.T, key, value string) {
|
||||
whitespace := []string{"", " ", "\f", "\t"}
|
||||
delimiters := []string{"", " ", "=", ":"}
|
||||
newlines := []string{"", "\r", "\n", "\r\n"}
|
||||
for _, dl := range delimiters {
|
||||
for _, ws1 := range whitespace {
|
||||
for _, ws2 := range whitespace {
|
||||
for _, nl := range newlines {
|
||||
// skip the one case where there is nothing between a key and a value
|
||||
if ws1 == "" && dl == "" && ws2 == "" && value != "" {
|
||||
continue
|
||||
}
|
||||
|
||||
input := fmt.Sprintf("%s%s%s%s%s%s", key, ws1, dl, ws2, value, nl)
|
||||
testKeyValue(t, input, key, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// tests whether key/value pairs exist for a given input.
|
||||
// keyvalues is expected to be an even number of strings of "key", "value", ...
|
||||
func testKeyValue(t *testing.T, input string, keyvalues ...string) {
|
||||
testKeyValuePrePostfix(t, "${", "}", input, keyvalues...)
|
||||
}
|
||||
|
||||
// tests whether key/value pairs exist for a given input.
|
||||
// keyvalues is expected to be an even number of strings of "key", "value", ...
|
||||
func testKeyValuePrePostfix(t *testing.T, prefix, postfix, input string, keyvalues ...string) {
|
||||
p, err := Load([]byte(input), ISO_8859_1)
|
||||
assert.Equal(t, err, nil)
|
||||
p.Prefix = prefix
|
||||
p.Postfix = postfix
|
||||
assertKeyValues(t, input, p, keyvalues...)
|
||||
}
|
||||
|
||||
// tests whether key/value pairs exist for a given input.
|
||||
// keyvalues is expected to be an even number of strings of "key", "value", ...
|
||||
func assertKeyValues(t *testing.T, input string, p *Properties, keyvalues ...string) {
|
||||
assert.Equal(t, p != nil, true, "want properties")
|
||||
assert.Equal(t, 2*p.Len(), len(keyvalues), "Odd number of key/value pairs.")
|
||||
|
||||
for i := 0; i < len(keyvalues); i += 2 {
|
||||
key, value := keyvalues[i], keyvalues[i+1]
|
||||
v, ok := p.Get(key)
|
||||
if !ok {
|
||||
t.Errorf("No key %q found (input=%q)", key, input)
|
||||
}
|
||||
if got, want := v, value; !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("Value %q does not match %q (input=%q)", v, value, input)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mustParse(t *testing.T, s string) *Properties {
|
||||
p, err := parse(s)
|
||||
if err != nil {
|
||||
t.Fatalf("parse failed with %s", err)
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// prints to stderr if the -verbose flag was given.
|
||||
func printf(format string, args ...interface{}) {
|
||||
if *verbose {
|
||||
fmt.Fprintf(os.Stderr, format, args...)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user