first commit
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
andrey1s
2021-04-27 14:58:19 +03:00
commit 913ca9672d
55 changed files with 4355 additions and 0 deletions

46
test/etcd.go Normal file
View File

@@ -0,0 +1,46 @@
package test
import (
"context"
"os"
"time"
client "go.etcd.io/etcd/client/v3"
)
func NewEtcd(ctx context.Context) (*client.Client, error) {
dsn, ok := os.LookupEnv("FDEVS_CONFIG_ETCD_HOST")
if !ok {
dsn = "127.0.0.1:2379"
}
et, err := client.New(client.Config{
Endpoints: []string{dsn},
DialTimeout: time.Second,
})
if err != nil {
return nil, err
}
values := map[string]string{
"fdevs/config/db_dsn": "pgsql://user@pass:127.0.0.1:5432",
"fdevs/config/duration": "12m",
"fdevs/config/port": "8080",
"fdevs/config/maintain": "true",
"fdevs/config/start_at": "2020-01-02T15:04:05Z",
"fdevs/config/percent": "0.064",
"fdevs/config/count": "2020",
"fdevs/config/int64": "2021",
"fdevs/config/uint64": "2022",
"fdevs/config/config": ConfigJSON,
}
for name, val := range values {
_, err = et.KV.Put(ctx, name, val)
if err != nil {
return nil, err
}
}
return et, nil
}

1038
test/fixture/config.ini Normal file

File diff suppressed because it is too large Load Diff

16
test/fixture/config.json Normal file
View File

@@ -0,0 +1,16 @@
{
"app": {
"name": {
"var": [
"name"
],
"title": "config title",
"timeout": "1m",
"success": true
}
},
"cfg": {
"duration": 1260000000000,
"enabled": true
}
}

31
test/fixture/config.toml Normal file
View File

@@ -0,0 +1,31 @@
title = "TOML Example"
[owner]
name = "Tom Preston-Werner"
dob = 1979-05-27T07:32:00-08:00 # First class dates
[database]
server = "192.168.1.1"
ports = [ 8001, 8001, 8002 ]
connection_max = 5000
enabled = true
[servers]
# Indentation (tabs and/or spaces) is allowed but not required
[servers.alpha]
ip = "10.0.0.1"
dc = "eqdc10"
[servers.beta]
ip = "10.0.0.2"
dc = "eqdc10"
[clients]
data = [ ["gamma", "delta"], [1, 2] ]
# Line breaks are OK when inside arrays
hosts = [
"alpha",
"omega"
]

12
test/fixture/config.yaml Normal file
View File

@@ -0,0 +1,12 @@
app:
name:
var:
- test
bool_var: true
duration_var: 21m
empty_var:
url_var: "http://google.com/"
time_var: "2020-01-02T15:04:05Z"
cfg:
duration: 21m
enabled: true

17
test/helpers.go Normal file
View File

@@ -0,0 +1,17 @@
package test
import (
"path/filepath"
"runtime"
)
func FixturePath(file string) string {
path := "fixture/"
_, filename, _, ok := runtime.Caller(0)
if ok {
path = filepath.Dir(filename) + "/" + path
}
return path + file
}

16
test/ini.go Normal file
View File

@@ -0,0 +1,16 @@
package test
import (
"log"
"gopkg.in/ini.v1"
)
func NewINI() *ini.File {
f, err := ini.Load(FixturePath("config.ini"))
if err != nil {
log.Fatal(err)
}
return f
}

15
test/json.go Normal file
View File

@@ -0,0 +1,15 @@
package test
import (
"io/ioutil"
"log"
)
func ReadFile(file string) []byte {
data, err := ioutil.ReadFile(FixturePath(file))
if err != nil {
log.Fatal(err)
}
return data
}

150
test/provider_suite.go Normal file
View File

@@ -0,0 +1,150 @@
package test
import (
"context"
"io/ioutil"
"path/filepath"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"gitoa.ru/go-4devs/config"
)
const (
DSN = "pgsql://user@pass:127.0.0.1:5432"
Namespace = "fdevs"
AppName = "config"
)
func Run(t *testing.T, provider config.Provider, read []Read) {
t.Helper()
prov := &ProviderSuite{
provider: provider,
read: read,
}
suite.Run(t, prov)
}
type ProviderSuite struct {
suite.Suite
provider config.Provider
read []Read
}
type Read struct {
Key config.Key
Assert func(t *testing.T, v config.Value)
}
const ConfigJSON = `{"duration":1260000000000,"enabled":true}`
type Config struct {
Duration time.Duration
Enabled bool
}
func NewReadConfig(key string) Read {
ex := &Config{
Duration: 21 * time.Minute,
Enabled: true,
}
return NewReadUnmarshal(key, ex, &Config{})
}
func NewReadUnmarshal(key string, expected, target interface{}) Read {
return Read{
Key: config.Key{
Namespace: "fdevs",
AppName: "config",
Name: key,
},
Assert: func(t *testing.T, v config.Value) {
t.Helper()
require.NoErrorf(t, v.Unmarshal(target), "unmarshal")
require.Equal(t, expected, target, "unmarshal")
},
}
}
func Time(value string) time.Time {
t, _ := time.Parse(time.RFC3339, value)
return t
}
// nolint: cyclop
func NewRead(key string, expected interface{}) Read {
return Read{
Key: config.Key{
Namespace: "fdevs",
AppName: "config",
Name: key,
},
Assert: func(t *testing.T, v config.Value) {
t.Helper()
var (
val interface{}
err error
short interface{}
)
switch expected.(type) {
case bool:
val, err = v.ParseBool()
short = v.Bool()
case int:
val, err = v.ParseInt()
short = v.Int()
case int64:
val, err = v.ParseInt64()
short = v.Int64()
case uint:
val, err = v.ParseUint()
short = v.Uint()
case uint64:
val, err = v.ParseUint64()
short = v.Uint64()
case string:
val, err = v.ParseString()
short = v.String()
case float64:
val, err = v.ParseFloat64()
short = v.Float64()
case time.Duration:
val, err = v.ParseDuration()
short = v.Duration()
case time.Time:
val, err = v.ParseTime()
short = v.Time()
default:
require.Fail(t, "unexpected type", "type:%+T", expected)
}
require.Equalf(t, val, short, "type:%T", expected)
require.NoErrorf(t, err, "type:%T", expected)
require.Equalf(t, expected, val, "type:%T", expected)
},
}
}
func (ps *ProviderSuite) TestReadKeys() {
ctx := context.Background()
for _, read := range ps.read {
val, err := ps.provider.Read(ctx, read.Key)
require.NoError(ps.T(), err, read.Key.String())
read.Assert(ps.T(), val.Value)
}
}
func LoadConfig(t *testing.T, path string) []byte {
t.Helper()
file, err := ioutil.ReadFile(filepath.Clean(path))
require.NoError(t, err)
return file
}

89
test/vault.go Normal file
View File

@@ -0,0 +1,89 @@
package test
import (
"bytes"
"context"
"encoding/json"
"net/http"
"os"
"github.com/hashicorp/vault/api"
)
const token = "dev"
func NewVault() (*api.Client, error) {
address, ok := os.LookupEnv("VAULT_DEV_LISTEN_ADDRESS")
if !ok {
address = "http://127.0.0.1:8200"
}
tokenID, ok := os.LookupEnv("VAULT_DEV_ROOT_TOKEN_ID")
if !ok {
tokenID = token
}
cl, err := api.NewClient(&api.Config{
Address: address,
})
if err != nil {
return nil, err
}
cl.SetToken(tokenID)
values := map[string]map[string]interface{}{
"database": {
"duration": 1260000000000,
"enabled": true,
},
"db": {
"dsn": DSN,
"timeout": "60s",
},
"example": {
"dsn": DSN,
"timeout": "60s",
},
}
for name, val := range values {
if err := create(address, tokenID, name, val); err != nil {
return nil, err
}
}
return cl, nil
}
func create(host, token, path string, data map[string]interface{}) error {
type Req struct {
Data interface{} `json:"data"`
}
b, err := json.Marshal(Req{Data: data})
if err != nil {
return err
}
body := bytes.NewBuffer(b)
req, err := http.NewRequestWithContext(
context.Background(),
http.MethodPost,
host+"/v1/secret/data/fdevs/config/"+path,
body,
)
if err != nil {
return err
}
req.Header.Set("X-Vault-Token", token)
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
return res.Body.Close()
}