Chore: Refactor GoConvey in provisioning package (#40892)

* refactor goconvey in some provisioning subpackages

* fix goconvey in provisioning/datasources

* remove goconvey from notifiers subpackage

* finally resolve goconvey in dashboards subpackage
pull/41138/head
Serge Zaitsev 4 years ago committed by GitHub
parent b80fbe03f0
commit 7b15cd0ed2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 698
      pkg/services/provisioning/dashboards/file_reader_test.go
  2. 351
      pkg/services/provisioning/datasources/config_reader_test.go
  3. 270
      pkg/services/provisioning/notifiers/config_reader_test.go
  4. 15
      pkg/services/provisioning/utils/utils_test.go
  5. 171
      pkg/services/provisioning/values/values_test.go

@ -17,7 +17,8 @@ import (
"github.com/grafana/grafana/pkg/util"
"github.com/grafana/grafana/pkg/infra/log"
. "github.com/smartystreets/goconvey/convey"
"github.com/stretchr/testify/require"
)
const (
@ -32,403 +33,432 @@ const (
var fakeService *fakeDashboardProvisioningService
func TestCreatingNewDashboardFileReader(t *testing.T) {
Convey("creating new dashboard file reader", t, func() {
cfg := &config{
setup := func() *config {
return &config{
Name: "Default",
Type: "file",
OrgID: 1,
Folder: "",
Options: map[string]interface{}{},
}
}
Convey("using path parameter", func() {
cfg.Options["path"] = defaultDashboards
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
So(err, ShouldBeNil)
So(reader.Path, ShouldNotEqual, "")
})
t.Run("using path parameter", func(t *testing.T) {
cfg := setup()
cfg.Options["path"] = defaultDashboards
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
require.NoError(t, err)
require.NotEqual(t, reader.Path, "")
})
Convey("using folder as options", func() {
cfg.Options["folder"] = defaultDashboards
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
So(err, ShouldBeNil)
So(reader.Path, ShouldNotEqual, "")
})
t.Run("using folder as options", func(t *testing.T) {
cfg := setup()
cfg.Options["folder"] = defaultDashboards
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
require.NoError(t, err)
require.NotEqual(t, reader.Path, "")
})
Convey("using foldersFromFilesStructure as options", func() {
cfg.Options["path"] = foldersFromFilesStructure
cfg.Options["foldersFromFilesStructure"] = true
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
So(err, ShouldBeNil)
So(reader.Path, ShouldNotEqual, "")
})
t.Run("using foldersFromFilesStructure as options", func(t *testing.T) {
cfg := setup()
cfg.Options["path"] = foldersFromFilesStructure
cfg.Options["foldersFromFilesStructure"] = true
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
require.NoError(t, err)
require.NotEqual(t, reader.Path, "")
})
Convey("using full path", func() {
fullPath := "/var/lib/grafana/dashboards"
if runtime.GOOS == "windows" {
fullPath = `c:\var\lib\grafana`
}
t.Run("using full path", func(t *testing.T) {
cfg := setup()
fullPath := "/var/lib/grafana/dashboards"
if runtime.GOOS == "windows" {
fullPath = `c:\var\lib\grafana`
}
cfg.Options["folder"] = fullPath
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
So(err, ShouldBeNil)
cfg.Options["folder"] = fullPath
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
require.NoError(t, err)
So(reader.Path, ShouldEqual, fullPath)
So(filepath.IsAbs(reader.Path), ShouldBeTrue)
})
require.Equal(t, reader.Path, fullPath)
require.True(t, filepath.IsAbs(reader.Path))
})
Convey("using relative path", func() {
cfg.Options["folder"] = defaultDashboards
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
So(err, ShouldBeNil)
t.Run("using relative path", func(t *testing.T) {
cfg := setup()
cfg.Options["folder"] = defaultDashboards
reader, err := NewDashboardFileReader(cfg, log.New("test-logger"), nil)
require.NoError(t, err)
resolvedPath := reader.resolvedPath()
So(filepath.IsAbs(resolvedPath), ShouldBeTrue)
})
resolvedPath := reader.resolvedPath()
require.True(t, filepath.IsAbs(resolvedPath))
})
}
func TestDashboardFileReader(t *testing.T) {
Convey("Dashboard file reader", t, func() {
logger := log.New("test.logger")
cfg := &config{}
origNewDashboardProvisioningService := dashboards.NewProvisioningService
defer func() {
dashboards.NewProvisioningService = origNewDashboardProvisioningService
}()
setup := func() {
bus.ClearBusHandlers()
origNewDashboardProvisioningService := dashboards.NewProvisioningService
Reset(func() {
dashboards.NewProvisioningService = origNewDashboardProvisioningService
})
fakeService = mockDashboardProvisioningService()
bus.AddHandler("test", mockGetDashboardQuery)
logger := log.New("test.logger")
Convey("Reading dashboards from disk", func() {
cfg := &config{
Name: "Default",
Type: "file",
OrgID: 1,
Folder: "",
Options: map[string]interface{}{},
}
cfg = &config{
Name: "Default",
Type: "file",
OrgID: 1,
Folder: "",
Options: map[string]interface{}{},
}
}
Convey("Can read default dashboard", func() {
cfg.Options["path"] = defaultDashboards
cfg.Folder = "Team A"
t.Run("Reading dashboards from disk", func(t *testing.T) {
t.Run("Can read default dashboard", func(t *testing.T) {
setup()
cfg.Options["path"] = defaultDashboards
cfg.Folder = "Team A"
reader, err := NewDashboardFileReader(cfg, logger, nil)
So(err, ShouldBeNil)
reader, err := NewDashboardFileReader(cfg, logger, nil)
require.NoError(t, err)
err = reader.walkDisk(context.Background())
So(err, ShouldBeNil)
err = reader.walkDisk(context.Background())
require.NoError(t, err)
folders := 0
dashboards := 0
folders := 0
dashboards := 0
for _, i := range fakeService.inserted {
if i.Dashboard.IsFolder {
folders++
} else {
dashboards++
}
for _, i := range fakeService.inserted {
if i.Dashboard.IsFolder {
folders++
} else {
dashboards++
}
}
So(folders, ShouldEqual, 1)
So(dashboards, ShouldEqual, 2)
})
Convey("Can read default dashboard and replace old version in database", func() {
cfg.Options["path"] = oneDashboard
stat, _ := os.Stat(oneDashboard + "/dashboard1.json")
fakeService.getDashboard = append(fakeService.getDashboard, &models.Dashboard{
Updated: stat.ModTime().AddDate(0, 0, -1),
Slug: "grafana",
})
require.Equal(t, folders, 1)
require.Equal(t, dashboards, 2)
})
reader, err := NewDashboardFileReader(cfg, logger, nil)
So(err, ShouldBeNil)
t.Run("Can read default dashboard and replace old version in database", func(t *testing.T) {
setup()
cfg.Options["path"] = oneDashboard
err = reader.walkDisk(context.Background())
So(err, ShouldBeNil)
stat, _ := os.Stat(oneDashboard + "/dashboard1.json")
So(len(fakeService.inserted), ShouldEqual, 1)
fakeService.getDashboard = append(fakeService.getDashboard, &models.Dashboard{
Updated: stat.ModTime().AddDate(0, 0, -1),
Slug: "grafana",
})
Convey("Dashboard with older timestamp and the same checksum will not replace imported dashboard", func() {
cfg.Options["path"] = oneDashboard
absPath, err := filepath.Abs(oneDashboard + "/dashboard1.json")
So(err, ShouldBeNil)
stat, err := os.Stat(oneDashboard + "/dashboard1.json")
So(err, ShouldBeNil)
file, err := os.Open(filepath.Clean(absPath))
So(err, ShouldBeNil)
t.Cleanup(func() {
_ = file.Close()
})
checksum, err := util.Md5Sum(file)
So(err, ShouldBeNil)
fakeService.provisioned = map[string][]*models.DashboardProvisioning{
"Default": {
{
Name: "Default",
ExternalId: absPath,
Updated: stat.ModTime().AddDate(0, 0, +1).Unix(),
CheckSum: checksum,
},
},
}
reader, err := NewDashboardFileReader(cfg, logger, nil)
So(err, ShouldBeNil)
reader, err := NewDashboardFileReader(cfg, logger, nil)
require.NoError(t, err)
err = reader.walkDisk(context.Background())
So(err, ShouldBeNil)
So(len(fakeService.inserted), ShouldEqual, 0)
})
err = reader.walkDisk(context.Background())
require.NoError(t, err)
Convey("Dashboard with older timestamp and different checksum will replace imported dashboard", func() {
cfg.Options["path"] = oneDashboard
absPath, err := filepath.Abs(oneDashboard + "/dashboard1.json")
So(err, ShouldBeNil)
stat, err := os.Stat(oneDashboard + "/dashboard1.json")
So(err, ShouldBeNil)
fakeService.provisioned = map[string][]*models.DashboardProvisioning{
"Default": {
{
Name: "Default",
ExternalId: absPath,
Updated: stat.ModTime().AddDate(0, 0, +1).Unix(),
CheckSum: "fakechecksum",
},
},
}
reader, err := NewDashboardFileReader(cfg, logger, nil)
So(err, ShouldBeNil)
require.Equal(t, len(fakeService.inserted), 1)
})
err = reader.walkDisk(context.Background())
So(err, ShouldBeNil)
So(len(fakeService.inserted), ShouldEqual, 1)
t.Run("Dashboard with older timestamp and the same checksum will not replace imported dashboard", func(t *testing.T) {
setup()
cfg.Options["path"] = oneDashboard
absPath, err := filepath.Abs(oneDashboard + "/dashboard1.json")
require.NoError(t, err)
stat, err := os.Stat(oneDashboard + "/dashboard1.json")
require.NoError(t, err)
file, err := os.Open(filepath.Clean(absPath))
require.NoError(t, err)
t.Cleanup(func() {
_ = file.Close()
})
Convey("Dashboard with newer timestamp and the same checksum will not replace imported dashboard", func() {
cfg.Options["path"] = oneDashboard
absPath, err := filepath.Abs(oneDashboard + "/dashboard1.json")
So(err, ShouldBeNil)
stat, err := os.Stat(oneDashboard + "/dashboard1.json")
So(err, ShouldBeNil)
file, err := os.Open(filepath.Clean(absPath))
So(err, ShouldBeNil)
t.Cleanup(func() {
_ = file.Close()
})
checksum, err := util.Md5Sum(file)
So(err, ShouldBeNil)
fakeService.provisioned = map[string][]*models.DashboardProvisioning{
"Default": {
{
Name: "Default",
ExternalId: absPath,
Updated: stat.ModTime().AddDate(0, 0, -1).Unix(),
CheckSum: checksum,
},
checksum, err := util.Md5Sum(file)
require.NoError(t, err)
fakeService.provisioned = map[string][]*models.DashboardProvisioning{
"Default": {
{
Name: "Default",
ExternalId: absPath,
Updated: stat.ModTime().AddDate(0, 0, +1).Unix(),
CheckSum: checksum,
},
}
},
}
reader, err := NewDashboardFileReader(cfg, logger, nil)
So(err, ShouldBeNil)
reader, err := NewDashboardFileReader(cfg, logger, nil)
require.NoError(t, err)
err = reader.walkDisk(context.Background())
So(err, ShouldBeNil)
So(len(fakeService.inserted), ShouldEqual, 0)
})
err = reader.walkDisk(context.Background())
require.NoError(t, err)
require.Equal(t, len(fakeService.inserted), 0)
})
t.Run("Dashboard with older timestamp and different checksum will replace imported dashboard", func(t *testing.T) {
setup()
cfg.Options["path"] = oneDashboard
absPath, err := filepath.Abs(oneDashboard + "/dashboard1.json")
require.NoError(t, err)
stat, err := os.Stat(oneDashboard + "/dashboard1.json")
require.NoError(t, err)
Convey("Dashboard with newer timestamp and different checksum should replace imported dashboard", func() {
cfg.Options["path"] = oneDashboard
absPath, err := filepath.Abs(oneDashboard + "/dashboard1.json")
So(err, ShouldBeNil)
stat, err := os.Stat(oneDashboard + "/dashboard1.json")
So(err, ShouldBeNil)
fakeService.provisioned = map[string][]*models.DashboardProvisioning{
"Default": {
{
Name: "Default",
ExternalId: absPath,
Updated: stat.ModTime().AddDate(0, 0, -1).Unix(),
CheckSum: "fakechecksum",
},
fakeService.provisioned = map[string][]*models.DashboardProvisioning{
"Default": {
{
Name: "Default",
ExternalId: absPath,
Updated: stat.ModTime().AddDate(0, 0, +1).Unix(),
CheckSum: "fakechecksum",
},
}
},
}
reader, err := NewDashboardFileReader(cfg, logger, nil)
require.NoError(t, err)
reader, err := NewDashboardFileReader(cfg, logger, nil)
So(err, ShouldBeNil)
err = reader.walkDisk(context.Background())
require.NoError(t, err)
require.Equal(t, len(fakeService.inserted), 1)
})
err = reader.walkDisk(context.Background())
So(err, ShouldBeNil)
So(len(fakeService.inserted), ShouldEqual, 1)
t.Run("Dashboard with newer timestamp and the same checksum will not replace imported dashboard", func(t *testing.T) {
setup()
cfg.Options["path"] = oneDashboard
absPath, err := filepath.Abs(oneDashboard + "/dashboard1.json")
require.NoError(t, err)
stat, err := os.Stat(oneDashboard + "/dashboard1.json")
require.NoError(t, err)
file, err := os.Open(filepath.Clean(absPath))
require.NoError(t, err)
t.Cleanup(func() {
_ = file.Close()
})
Convey("Overrides id from dashboard.json files", func() {
cfg.Options["path"] = containingID
checksum, err := util.Md5Sum(file)
require.NoError(t, err)
reader, err := NewDashboardFileReader(cfg, logger, nil)
So(err, ShouldBeNil)
fakeService.provisioned = map[string][]*models.DashboardProvisioning{
"Default": {
{
Name: "Default",
ExternalId: absPath,
Updated: stat.ModTime().AddDate(0, 0, -1).Unix(),
CheckSum: checksum,
},
},
}
err = reader.walkDisk(context.Background())
So(err, ShouldBeNil)
reader, err := NewDashboardFileReader(cfg, logger, nil)
require.NoError(t, err)
So(len(fakeService.inserted), ShouldEqual, 1)
})
err = reader.walkDisk(context.Background())
require.NoError(t, err)
require.Equal(t, len(fakeService.inserted), 0)
})
Convey("Get folder from files structure", func() {
cfg.Options["path"] = foldersFromFilesStructure
cfg.Options["foldersFromFilesStructure"] = true
t.Run("Dashboard with newer timestamp and different checksum should replace imported dashboard", func(t *testing.T) {
setup()
cfg.Options["path"] = oneDashboard
absPath, err := filepath.Abs(oneDashboard + "/dashboard1.json")
require.NoError(t, err)
stat, err := os.Stat(oneDashboard + "/dashboard1.json")
require.NoError(t, err)
reader, err := NewDashboardFileReader(cfg, logger, nil)
So(err, ShouldBeNil)
fakeService.provisioned = map[string][]*models.DashboardProvisioning{
"Default": {
{
Name: "Default",
ExternalId: absPath,
Updated: stat.ModTime().AddDate(0, 0, -1).Unix(),
CheckSum: "fakechecksum",
},
},
}
err = reader.walkDisk(context.Background())
So(err, ShouldBeNil)
reader, err := NewDashboardFileReader(cfg, logger, nil)
require.NoError(t, err)
So(len(fakeService.inserted), ShouldEqual, 5)
err = reader.walkDisk(context.Background())
require.NoError(t, err)
require.Equal(t, len(fakeService.inserted), 1)
})
foldersCount := 0
for _, d := range fakeService.inserted {
if d.Dashboard.IsFolder {
foldersCount++
}
}
So(foldersCount, ShouldEqual, 2)
foldersAndDashboards := make(map[string]struct{}, 5)
for _, d := range fakeService.inserted {
title := d.Dashboard.Title
if _, ok := foldersAndDashboards[title]; ok {
So(fmt.Errorf("dashboard title %q already exists", title), ShouldBeNil)
}
switch title {
case "folderOne", "folderTwo":
So(d.Dashboard.IsFolder, ShouldBeTrue)
case "Grafana1", "Grafana2", "RootDashboard":
So(d.Dashboard.IsFolder, ShouldBeFalse)
default:
So(fmt.Errorf("unknown dashboard title %q", title), ShouldBeNil)
}
foldersAndDashboards[title] = struct{}{}
}
})
t.Run("Overrides id from dashboard.json files", func(t *testing.T) {
setup()
cfg.Options["path"] = containingID
Convey("Invalid configuration should return error", func() {
cfg := &config{
Name: "Default",
Type: "file",
OrgID: 1,
Folder: "",
}
reader, err := NewDashboardFileReader(cfg, logger, nil)
require.NoError(t, err)
_, err := NewDashboardFileReader(cfg, logger, nil)
So(err, ShouldNotBeNil)
})
err = reader.walkDisk(context.Background())
require.NoError(t, err)
Convey("Broken dashboards should not cause error", func() {
cfg.Options["path"] = brokenDashboards
require.Equal(t, len(fakeService.inserted), 1)
})
_, err := NewDashboardFileReader(cfg, logger, nil)
So(err, ShouldBeNil)
})
t.Run("Get folder from files structure", func(t *testing.T) {
setup()
cfg.Options["path"] = foldersFromFilesStructure
cfg.Options["foldersFromFilesStructure"] = true
Convey("Two dashboard providers should be able to provisioned the same dashboard without uid", func() {
cfg1 := &config{Name: "1", Type: "file", OrgID: 1, Folder: "f1", Options: map[string]interface{}{"path": containingID}}
cfg2 := &config{Name: "2", Type: "file", OrgID: 1, Folder: "f2", Options: map[string]interface{}{"path": containingID}}
reader, err := NewDashboardFileReader(cfg, logger, nil)
require.NoError(t, err)
reader1, err := NewDashboardFileReader(cfg1, logger, nil)
So(err, ShouldBeNil)
err = reader.walkDisk(context.Background())
require.NoError(t, err)
err = reader1.walkDisk(context.Background())
So(err, ShouldBeNil)
require.Equal(t, len(fakeService.inserted), 5)
reader2, err := NewDashboardFileReader(cfg2, logger, nil)
So(err, ShouldBeNil)
foldersCount := 0
for _, d := range fakeService.inserted {
if d.Dashboard.IsFolder {
foldersCount++
}
}
require.Equal(t, foldersCount, 2)
err = reader2.walkDisk(context.Background())
So(err, ShouldBeNil)
foldersAndDashboards := make(map[string]struct{}, 5)
for _, d := range fakeService.inserted {
title := d.Dashboard.Title
if _, ok := foldersAndDashboards[title]; ok {
require.Nil(t, fmt.Errorf("dashboard title %q already exists", title))
}
var folderCount int
var dashCount int
for _, o := range fakeService.inserted {
if o.Dashboard.IsFolder {
folderCount++
} else {
dashCount++
}
switch title {
case "folderOne", "folderTwo":
require.True(t, d.Dashboard.IsFolder)
case "Grafana1", "Grafana2", "RootDashboard":
require.False(t, d.Dashboard.IsFolder)
default:
require.Nil(t, fmt.Errorf("unknown dashboard title %q", title))
}
So(folderCount, ShouldEqual, 2)
So(dashCount, ShouldEqual, 2)
})
foldersAndDashboards[title] = struct{}{}
}
})
Convey("Should not create new folder if folder name is missing", func() {
t.Run("Invalid configuration should return error", func(t *testing.T) {
setup()
cfg := &config{
Name: "Default",
Type: "file",
OrgID: 1,
Folder: "",
Options: map[string]interface{}{
"folder": defaultDashboards,
},
}
_, err := getOrCreateFolderID(context.Background(), cfg, fakeService, cfg.Folder)
So(err, ShouldEqual, ErrFolderNameMissing)
_, err := NewDashboardFileReader(cfg, logger, nil)
require.NotNil(t, err)
})
Convey("can get or Create dashboard folder", func() {
cfg := &config{
Name: "Default",
Type: "file",
OrgID: 1,
Folder: "TEAM A",
Options: map[string]interface{}{
"folder": defaultDashboards,
},
}
t.Run("Broken dashboards should not cause error", func(t *testing.T) {
setup()
cfg.Options["path"] = brokenDashboards
folderID, err := getOrCreateFolderID(context.Background(), cfg, fakeService, cfg.Folder)
So(err, ShouldBeNil)
inserted := false
for _, d := range fakeService.inserted {
if d.Dashboard.IsFolder && d.Dashboard.Id == folderID {
inserted = true
_, err := NewDashboardFileReader(cfg, logger, nil)
require.NoError(t, err)
})
t.Run("Two dashboard providers should be able to provisioned the same dashboard without uid", func(t *testing.T) {
setup()
cfg1 := &config{Name: "1", Type: "file", OrgID: 1, Folder: "f1", Options: map[string]interface{}{"path": containingID}}
cfg2 := &config{Name: "2", Type: "file", OrgID: 1, Folder: "f2", Options: map[string]interface{}{"path": containingID}}
reader1, err := NewDashboardFileReader(cfg1, logger, nil)
require.NoError(t, err)
err = reader1.walkDisk(context.Background())
require.NoError(t, err)
reader2, err := NewDashboardFileReader(cfg2, logger, nil)
require.NoError(t, err)
err = reader2.walkDisk(context.Background())
require.NoError(t, err)
var folderCount int
var dashCount int
for _, o := range fakeService.inserted {
if o.Dashboard.IsFolder {
folderCount++
} else {
dashCount++
}
}
So(len(fakeService.inserted), ShouldEqual, 1)
So(inserted, ShouldBeTrue)
require.Equal(t, folderCount, 2)
require.Equal(t, dashCount, 2)
})
})
Convey("Walking the folder with dashboards", func() {
noFiles := map[string]os.FileInfo{}
t.Run("Should not create new folder if folder name is missing", func(t *testing.T) {
setup()
cfg := &config{
Name: "Default",
Type: "file",
OrgID: 1,
Folder: "",
Options: map[string]interface{}{
"folder": defaultDashboards,
},
}
Convey("should skip dirs that starts with .", func() {
shouldSkip := createWalkFn(noFiles)("path", &FakeFileInfo{isDirectory: true, name: ".folder"}, nil)
So(shouldSkip, ShouldEqual, filepath.SkipDir)
})
_, err := getOrCreateFolderID(context.Background(), cfg, fakeService, cfg.Folder)
require.Equal(t, err, ErrFolderNameMissing)
})
Convey("should keep walking if file is not .json", func() {
shouldSkip := createWalkFn(noFiles)("path", &FakeFileInfo{isDirectory: true, name: "folder"}, nil)
So(shouldSkip, ShouldBeNil)
})
t.Run("can get or Create dashboard folder", func(t *testing.T) {
setup()
cfg := &config{
Name: "Default",
Type: "file",
OrgID: 1,
Folder: "TEAM A",
Options: map[string]interface{}{
"folder": defaultDashboards,
},
}
folderID, err := getOrCreateFolderID(context.Background(), cfg, fakeService, cfg.Folder)
require.NoError(t, err)
inserted := false
for _, d := range fakeService.inserted {
if d.Dashboard.IsFolder && d.Dashboard.Id == folderID {
inserted = true
}
}
require.Equal(t, len(fakeService.inserted), 1)
require.True(t, inserted)
})
t.Run("Walking the folder with dashboards", func(t *testing.T) {
setup()
noFiles := map[string]os.FileInfo{}
t.Run("should skip dirs that starts with .", func(t *testing.T) {
shouldSkip := createWalkFn(noFiles)("path", &FakeFileInfo{isDirectory: true, name: ".folder"}, nil)
require.Equal(t, shouldSkip, filepath.SkipDir)
})
Convey("Given missing dashboard file", func() {
cfg := &config{
t.Run("should keep walking if file is not .json", func(t *testing.T) {
shouldSkip := createWalkFn(noFiles)("path", &FakeFileInfo{isDirectory: true, name: "folder"}, nil)
require.Nil(t, shouldSkip)
})
})
t.Run("Given missing dashboard file", func(t *testing.T) {
absPath1, err := filepath.Abs(unprovision + "/dashboard1.json")
require.NoError(t, err)
// This one does not exist on disk, simulating a deleted file
absPath2, err := filepath.Abs(unprovision + "/dashboard2.json")
require.NoError(t, err)
setupFakeService := func() {
setup()
cfg = &config{
Name: "Default",
Type: "file",
OrgID: 1,
@ -442,44 +472,40 @@ func TestDashboardFileReader(t *testing.T) {
{Dashboard: &models.Dashboard{Id: 2}},
}
absPath1, err := filepath.Abs(unprovision + "/dashboard1.json")
So(err, ShouldBeNil)
// This one does not exist on disk, simulating a deleted file
absPath2, err := filepath.Abs(unprovision + "/dashboard2.json")
So(err, ShouldBeNil)
fakeService.provisioned = map[string][]*models.DashboardProvisioning{
"Default": {
{DashboardId: 1, Name: "Default", ExternalId: absPath1},
{DashboardId: 2, Name: "Default", ExternalId: absPath2},
},
}
}
Convey("Missing dashboard should be unprovisioned if DisableDeletion = true", func() {
cfg.DisableDeletion = true
t.Run("Missing dashboard should be unprovisioned if DisableDeletion = true", func(t *testing.T) {
setupFakeService()
cfg.DisableDeletion = true
reader, err := NewDashboardFileReader(cfg, logger, nil)
So(err, ShouldBeNil)
reader, err := NewDashboardFileReader(cfg, logger, nil)
require.NoError(t, err)
err = reader.walkDisk(context.Background())
So(err, ShouldBeNil)
err = reader.walkDisk(context.Background())
require.NoError(t, err)
So(len(fakeService.provisioned["Default"]), ShouldEqual, 1)
So(fakeService.provisioned["Default"][0].ExternalId, ShouldEqual, absPath1)
})
require.Equal(t, len(fakeService.provisioned["Default"]), 1)
require.Equal(t, fakeService.provisioned["Default"][0].ExternalId, absPath1)
})
Convey("Missing dashboard should be deleted if DisableDeletion = false", func() {
reader, err := NewDashboardFileReader(cfg, logger, nil)
So(err, ShouldBeNil)
t.Run("Missing dashboard should be deleted if DisableDeletion = false", func(t *testing.T) {
setupFakeService()
reader, err := NewDashboardFileReader(cfg, logger, nil)
require.NoError(t, err)
err = reader.walkDisk(context.Background())
So(err, ShouldBeNil)
err = reader.walkDisk(context.Background())
require.NoError(t, err)
So(len(fakeService.provisioned["Default"]), ShouldEqual, 1)
So(fakeService.provisioned["Default"][0].ExternalId, ShouldEqual, absPath1)
So(len(fakeService.inserted), ShouldEqual, 1)
So(fakeService.inserted[0].Dashboard.Id, ShouldEqual, 1)
})
require.Equal(t, len(fakeService.provisioned["Default"]), 1)
require.Equal(t, fakeService.provisioned["Default"][0].ExternalId, absPath1)
require.Equal(t, len(fakeService.inserted), 1)
require.Equal(t, fakeService.inserted[0].Dashboard.Id, int64(1))
})
})
}

@ -9,7 +9,7 @@ import (
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/models"
. "github.com/smartystreets/goconvey/convey"
"github.com/stretchr/testify/require"
)
var (
@ -29,7 +29,7 @@ var (
)
func TestDatasourceAsConfig(t *testing.T) {
Convey("Testing datasource as configuration", t, func() {
setup := func() {
fakeRepo = &fakeRepository{}
bus.ClearBusHandlers()
bus.AddHandler("test", mockDelete)
@ -37,226 +37,229 @@ func TestDatasourceAsConfig(t *testing.T) {
bus.AddHandler("test", mockUpdate)
bus.AddHandler("test", mockGet)
bus.AddHandler("test", mockGetOrg)
}
t.Run("apply default values when missing", func(t *testing.T) {
setup()
dc := newDatasourceProvisioner(logger)
err := dc.applyChanges(context.Background(), withoutDefaults)
if err != nil {
t.Fatalf("applyChanges return an error %v", err)
}
require.Equal(t, len(fakeRepo.inserted), 1)
require.Equal(t, fakeRepo.inserted[0].OrgId, int64(1))
require.Equal(t, fakeRepo.inserted[0].Access, models.DsAccess("proxy"))
})
t.Run("no datasource in database", func(t *testing.T) {
setup()
dc := newDatasourceProvisioner(logger)
err := dc.applyChanges(context.Background(), twoDatasourcesConfig)
if err != nil {
t.Fatalf("applyChanges return an error %v", err)
}
require.Equal(t, len(fakeRepo.deleted), 0)
require.Equal(t, len(fakeRepo.inserted), 2)
require.Equal(t, len(fakeRepo.updated), 0)
})
t.Run("One datasource in database with same name", func(t *testing.T) {
setup()
fakeRepo.loadAll = []*models.DataSource{
{Name: "Graphite", OrgId: 1, Id: 1},
}
Convey("apply default values when missing", func() {
t.Run("should update one datasource", func(t *testing.T) {
dc := newDatasourceProvisioner(logger)
err := dc.applyChanges(context.Background(), withoutDefaults)
err := dc.applyChanges(context.Background(), twoDatasourcesConfig)
if err != nil {
t.Fatalf("applyChanges return an error %v", err)
}
So(len(fakeRepo.inserted), ShouldEqual, 1)
So(fakeRepo.inserted[0].OrgId, ShouldEqual, 1)
So(fakeRepo.inserted[0].Access, ShouldEqual, "proxy")
require.Equal(t, len(fakeRepo.deleted), 0)
require.Equal(t, len(fakeRepo.inserted), 1)
require.Equal(t, len(fakeRepo.updated), 1)
})
})
Convey("One configured datasource", func() {
Convey("no datasource in database", func() {
dc := newDatasourceProvisioner(logger)
err := dc.applyChanges(context.Background(), twoDatasourcesConfig)
if err != nil {
t.Fatalf("applyChanges return an error %v", err)
}
So(len(fakeRepo.deleted), ShouldEqual, 0)
So(len(fakeRepo.inserted), ShouldEqual, 2)
So(len(fakeRepo.updated), ShouldEqual, 0)
})
Convey("One datasource in database with same name", func() {
fakeRepo.loadAll = []*models.DataSource{
{Name: "Graphite", OrgId: 1, Id: 1},
}
Convey("should update one datasource", func() {
dc := newDatasourceProvisioner(logger)
err := dc.applyChanges(context.Background(), twoDatasourcesConfig)
if err != nil {
t.Fatalf("applyChanges return an error %v", err)
}
So(len(fakeRepo.deleted), ShouldEqual, 0)
So(len(fakeRepo.inserted), ShouldEqual, 1)
So(len(fakeRepo.updated), ShouldEqual, 1)
})
})
t.Run("Two datasources with is_default", func(t *testing.T) {
setup()
dc := newDatasourceProvisioner(logger)
err := dc.applyChanges(context.Background(), doubleDatasourcesConfig)
t.Run("should raise error", func(t *testing.T) { require.Equal(t, err, ErrInvalidConfigToManyDefault) })
})
Convey("Two datasources with is_default", func() {
dc := newDatasourceProvisioner(logger)
err := dc.applyChanges(context.Background(), doubleDatasourcesConfig)
Convey("should raise error", func() {
So(err, ShouldEqual, ErrInvalidConfigToManyDefault)
})
})
t.Run("Multiple datasources in different organizations with isDefault in each organization", func(t *testing.T) {
setup()
dc := newDatasourceProvisioner(logger)
err := dc.applyChanges(context.Background(), multipleOrgsWithDefault)
t.Run("should not raise error", func(t *testing.T) {
require.NoError(t, err)
require.Equal(t, len(fakeRepo.inserted), 4)
require.True(t, fakeRepo.inserted[0].IsDefault)
require.Equal(t, fakeRepo.inserted[0].OrgId, int64(1))
require.True(t, fakeRepo.inserted[2].IsDefault)
require.Equal(t, fakeRepo.inserted[2].OrgId, int64(2))
})
})
Convey("Multiple datasources in different organizations with isDefault in each organization", func() {
dc := newDatasourceProvisioner(logger)
err := dc.applyChanges(context.Background(), multipleOrgsWithDefault)
Convey("should not raise error", func() {
So(err, ShouldBeNil)
So(len(fakeRepo.inserted), ShouldEqual, 4)
So(fakeRepo.inserted[0].IsDefault, ShouldBeTrue)
So(fakeRepo.inserted[0].OrgId, ShouldEqual, 1)
So(fakeRepo.inserted[2].IsDefault, ShouldBeTrue)
So(fakeRepo.inserted[2].OrgId, ShouldEqual, 2)
})
})
t.Run("Two configured datasource and purge others ", func(t *testing.T) {
setup()
t.Run("two other datasources in database", func(t *testing.T) {
fakeRepo.loadAll = []*models.DataSource{
{Name: "old-graphite", OrgId: 1, Id: 1},
{Name: "old-graphite2", OrgId: 1, Id: 2},
}
Convey("Two configured datasource and purge others ", func() {
Convey("two other datasources in database", func() {
fakeRepo.loadAll = []*models.DataSource{
{Name: "old-graphite", OrgId: 1, Id: 1},
{Name: "old-graphite2", OrgId: 1, Id: 2},
t.Run("should have two new datasources", func(t *testing.T) {
dc := newDatasourceProvisioner(logger)
err := dc.applyChanges(context.Background(), twoDatasourcesConfigPurgeOthers)
if err != nil {
t.Fatalf("applyChanges return an error %v", err)
}
Convey("should have two new datasources", func() {
dc := newDatasourceProvisioner(logger)
err := dc.applyChanges(context.Background(), twoDatasourcesConfigPurgeOthers)
if err != nil {
t.Fatalf("applyChanges return an error %v", err)
}
So(len(fakeRepo.deleted), ShouldEqual, 2)
So(len(fakeRepo.inserted), ShouldEqual, 2)
So(len(fakeRepo.updated), ShouldEqual, 0)
})
require.Equal(t, len(fakeRepo.deleted), 2)
require.Equal(t, len(fakeRepo.inserted), 2)
require.Equal(t, len(fakeRepo.updated), 0)
})
})
})
Convey("Two configured datasource and purge others = false", func() {
Convey("two other datasources in database", func() {
fakeRepo.loadAll = []*models.DataSource{
{Name: "Graphite", OrgId: 1, Id: 1},
{Name: "old-graphite2", OrgId: 1, Id: 2},
t.Run("Two configured datasource and purge others = false", func(t *testing.T) {
setup()
t.Run("two other datasources in database", func(t *testing.T) {
fakeRepo.loadAll = []*models.DataSource{
{Name: "Graphite", OrgId: 1, Id: 1},
{Name: "old-graphite2", OrgId: 1, Id: 2},
}
t.Run("should have two new datasources", func(t *testing.T) {
dc := newDatasourceProvisioner(logger)
err := dc.applyChanges(context.Background(), twoDatasourcesConfig)
if err != nil {
t.Fatalf("applyChanges return an error %v", err)
}
Convey("should have two new datasources", func() {
dc := newDatasourceProvisioner(logger)
err := dc.applyChanges(context.Background(), twoDatasourcesConfig)
if err != nil {
t.Fatalf("applyChanges return an error %v", err)
}
So(len(fakeRepo.deleted), ShouldEqual, 0)
So(len(fakeRepo.inserted), ShouldEqual, 1)
So(len(fakeRepo.updated), ShouldEqual, 1)
})
require.Equal(t, len(fakeRepo.deleted), 0)
require.Equal(t, len(fakeRepo.inserted), 1)
require.Equal(t, len(fakeRepo.updated), 1)
})
})
})
Convey("broken yaml should return error", func() {
reader := &configReader{}
_, err := reader.readConfig(brokenYaml)
So(err, ShouldNotBeNil)
})
t.Run("broken yaml should return error", func(t *testing.T) {
reader := &configReader{}
_, err := reader.readConfig(brokenYaml)
require.NotNil(t, err)
})
Convey("invalid access should warn about invalid value and return 'proxy'", func() {
reader := &configReader{log: logger}
configs, err := reader.readConfig(invalidAccess)
So(err, ShouldBeNil)
So(configs[0].Datasources[0].Access, ShouldEqual, models.DS_ACCESS_PROXY)
})
t.Run("invalid access should warn about invalid value and return 'proxy'", func(t *testing.T) {
reader := &configReader{log: logger}
configs, err := reader.readConfig(invalidAccess)
require.NoError(t, err)
require.Equal(t, configs[0].Datasources[0].Access, models.DS_ACCESS_PROXY)
})
Convey("skip invalid directory", func() {
cfgProvider := &configReader{log: log.New("test logger")}
cfg, err := cfgProvider.readConfig("./invalid-directory")
if err != nil {
t.Fatalf("readConfig return an error %v", err)
}
t.Run("skip invalid directory", func(t *testing.T) {
cfgProvider := &configReader{log: log.New("test logger")}
cfg, err := cfgProvider.readConfig("./invalid-directory")
if err != nil {
t.Fatalf("readConfig return an error %v", err)
}
So(len(cfg), ShouldEqual, 0)
})
require.Equal(t, len(cfg), 0)
})
Convey("can read all properties from version 1", func() {
_ = os.Setenv("TEST_VAR", "name")
cfgProvider := &configReader{log: log.New("test logger")}
cfg, err := cfgProvider.readConfig(allProperties)
_ = os.Unsetenv("TEST_VAR")
if err != nil {
t.Fatalf("readConfig return an error %v", err)
}
t.Run("can read all properties from version 1", func(t *testing.T) {
_ = os.Setenv("TEST_VAR", "name")
cfgProvider := &configReader{log: log.New("test logger")}
cfg, err := cfgProvider.readConfig(allProperties)
_ = os.Unsetenv("TEST_VAR")
if err != nil {
t.Fatalf("readConfig return an error %v", err)
}
So(len(cfg), ShouldEqual, 3)
require.Equal(t, len(cfg), 3)
dsCfg := cfg[0]
dsCfg := cfg[0]
So(dsCfg.APIVersion, ShouldEqual, 1)
require.Equal(t, dsCfg.APIVersion, int64(1))
validateDatasourceV1(dsCfg)
validateDeleteDatasources(dsCfg)
validateDatasourceV1(t, dsCfg)
validateDeleteDatasources(t, dsCfg)
dsCount := 0
delDsCount := 0
dsCount := 0
delDsCount := 0
for _, c := range cfg {
dsCount += len(c.Datasources)
delDsCount += len(c.DeleteDatasources)
}
for _, c := range cfg {
dsCount += len(c.Datasources)
delDsCount += len(c.DeleteDatasources)
}
So(dsCount, ShouldEqual, 2)
So(delDsCount, ShouldEqual, 1)
})
require.Equal(t, dsCount, 2)
require.Equal(t, delDsCount, 1)
})
Convey("can read all properties from version 0", func() {
cfgProvider := &configReader{log: log.New("test logger")}
cfg, err := cfgProvider.readConfig(versionZero)
if err != nil {
t.Fatalf("readConfig return an error %v", err)
}
t.Run("can read all properties from version 0", func(t *testing.T) {
cfgProvider := &configReader{log: log.New("test logger")}
cfg, err := cfgProvider.readConfig(versionZero)
if err != nil {
t.Fatalf("readConfig return an error %v", err)
}
So(len(cfg), ShouldEqual, 1)
require.Equal(t, len(cfg), 1)
dsCfg := cfg[0]
dsCfg := cfg[0]
So(dsCfg.APIVersion, ShouldEqual, 0)
require.Equal(t, dsCfg.APIVersion, int64(0))
validateDatasource(dsCfg)
validateDeleteDatasources(dsCfg)
})
validateDatasource(t, dsCfg)
validateDeleteDatasources(t, dsCfg)
})
}
func validateDeleteDatasources(dsCfg *configs) {
So(len(dsCfg.DeleteDatasources), ShouldEqual, 1)
func validateDeleteDatasources(t *testing.T, dsCfg *configs) {
require.Equal(t, len(dsCfg.DeleteDatasources), 1)
deleteDs := dsCfg.DeleteDatasources[0]
So(deleteDs.Name, ShouldEqual, "old-graphite3")
So(deleteDs.OrgID, ShouldEqual, 2)
require.Equal(t, deleteDs.Name, "old-graphite3")
require.Equal(t, deleteDs.OrgID, int64(2))
}
func validateDatasource(dsCfg *configs) {
func validateDatasource(t *testing.T, dsCfg *configs) {
ds := dsCfg.Datasources[0]
So(ds.Name, ShouldEqual, "name")
So(ds.Type, ShouldEqual, "type")
So(ds.Access, ShouldEqual, models.DS_ACCESS_PROXY)
So(ds.OrgID, ShouldEqual, 2)
So(ds.URL, ShouldEqual, "url")
So(ds.User, ShouldEqual, "user")
So(ds.Password, ShouldEqual, "password")
So(ds.Database, ShouldEqual, "database")
So(ds.BasicAuth, ShouldBeTrue)
So(ds.BasicAuthUser, ShouldEqual, "basic_auth_user")
So(ds.BasicAuthPassword, ShouldEqual, "basic_auth_password")
So(ds.WithCredentials, ShouldBeTrue)
So(ds.IsDefault, ShouldBeTrue)
So(ds.Editable, ShouldBeTrue)
So(ds.Version, ShouldEqual, 10)
So(len(ds.JSONData), ShouldBeGreaterThan, 2)
So(ds.JSONData["graphiteVersion"], ShouldEqual, "1.1")
So(ds.JSONData["tlsAuth"], ShouldEqual, true)
So(ds.JSONData["tlsAuthWithCACert"], ShouldEqual, true)
So(len(ds.SecureJSONData), ShouldBeGreaterThan, 2)
So(ds.SecureJSONData["tlsCACert"], ShouldEqual, "MjNOcW9RdkbUDHZmpco2HCYzVq9dE+i6Yi+gmUJotq5CDA==")
So(ds.SecureJSONData["tlsClientCert"], ShouldEqual, "ckN0dGlyMXN503YNfjTcf9CV+GGQneN+xmAclQ==")
So(ds.SecureJSONData["tlsClientKey"], ShouldEqual, "ZkN4aG1aNkja/gKAB1wlnKFIsy2SRDq4slrM0A==")
require.Equal(t, ds.Name, "name")
require.Equal(t, ds.Type, "type")
require.Equal(t, ds.Access, models.DS_ACCESS_PROXY)
require.Equal(t, ds.OrgID, int64(2))
require.Equal(t, ds.URL, "url")
require.Equal(t, ds.User, "user")
require.Equal(t, ds.Password, "password")
require.Equal(t, ds.Database, "database")
require.True(t, ds.BasicAuth)
require.Equal(t, ds.BasicAuthUser, "basic_auth_user")
require.Equal(t, ds.BasicAuthPassword, "basic_auth_password")
require.True(t, ds.WithCredentials)
require.True(t, ds.IsDefault)
require.True(t, ds.Editable)
require.Equal(t, ds.Version, 10)
require.Greater(t, len(ds.JSONData), 2)
require.Equal(t, ds.JSONData["graphiteVersion"], "1.1")
require.Equal(t, ds.JSONData["tlsAuth"], true)
require.Equal(t, ds.JSONData["tlsAuthWithCACert"], true)
require.Greater(t, len(ds.SecureJSONData), 2)
require.Equal(t, ds.SecureJSONData["tlsCACert"], "MjNOcW9RdkbUDHZmpco2HCYzVq9dE+i6Yi+gmUJotq5CDA==")
require.Equal(t, ds.SecureJSONData["tlsClientCert"], "ckN0dGlyMXN503YNfjTcf9CV+GGQneN+xmAclQ==")
require.Equal(t, ds.SecureJSONData["tlsClientKey"], "ZkN4aG1aNkja/gKAB1wlnKFIsy2SRDq4slrM0A==")
}
func validateDatasourceV1(dsCfg *configs) {
validateDatasource(dsCfg)
func validateDatasourceV1(t *testing.T, dsCfg *configs) {
validateDatasource(t, dsCfg)
ds := dsCfg.Datasources[0]
So(ds.UID, ShouldEqual, "test_uid")
require.Equal(t, ds.UID, "test_uid")
}
type fakeRepository struct {

@ -12,7 +12,8 @@ import (
"github.com/grafana/grafana/pkg/services/alerting/notifiers"
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
"github.com/grafana/grafana/pkg/services/sqlstore"
. "github.com/smartystreets/goconvey/convey"
"github.com/stretchr/testify/require"
)
var (
@ -29,31 +30,35 @@ var (
)
func TestNotificationAsConfig(t *testing.T) {
var sqlStore *sqlstore.SQLStore
logger := log.New("fake.log")
Convey("Testing notification as configuration", t, func() {
sqlStore := sqlstore.InitTestDB(t)
setupBusHandlers(sqlStore)
t.Run("Testing notification as configuration", func(t *testing.T) {
setup := func() {
sqlStore = sqlstore.InitTestDB(t)
setupBusHandlers(sqlStore)
for i := 1; i < 5; i++ {
orgCommand := models.CreateOrgCommand{Name: fmt.Sprintf("Main Org. %v", i)}
err := sqlstore.CreateOrg(&orgCommand)
So(err, ShouldBeNil)
}
for i := 1; i < 5; i++ {
orgCommand := models.CreateOrgCommand{Name: fmt.Sprintf("Main Org. %v", i)}
err := sqlstore.CreateOrg(&orgCommand)
require.NoError(t, err)
}
alerting.RegisterNotifier(&alerting.NotifierPlugin{
Type: "slack",
Name: "slack",
Factory: notifiers.NewSlackNotifier,
})
alerting.RegisterNotifier(&alerting.NotifierPlugin{
Type: "slack",
Name: "slack",
Factory: notifiers.NewSlackNotifier,
})
alerting.RegisterNotifier(&alerting.NotifierPlugin{
Type: "email",
Name: "email",
Factory: notifiers.NewEmailNotifier,
})
alerting.RegisterNotifier(&alerting.NotifierPlugin{
Type: "email",
Name: "email",
Factory: notifiers.NewEmailNotifier,
})
}
Convey("Can read correct properties", func() {
t.Run("Can read correct properties", func(t *testing.T) {
setup()
_ = os.Setenv("TEST_VAR", "default")
cfgProvider := &configReader{
encryptionService: ossencryption.ProvideService(),
@ -65,73 +70,74 @@ func TestNotificationAsConfig(t *testing.T) {
if err != nil {
t.Fatalf("readConfig return an error %v", err)
}
So(len(cfg), ShouldEqual, 1)
require.Equal(t, len(cfg), 1)
ntCfg := cfg[0]
nts := ntCfg.Notifications
So(len(nts), ShouldEqual, 4)
require.Equal(t, len(nts), 4)
nt := nts[0]
So(nt.Name, ShouldEqual, "default-slack-notification")
So(nt.Type, ShouldEqual, "slack")
So(nt.OrgID, ShouldEqual, 2)
So(nt.UID, ShouldEqual, "notifier1")
So(nt.IsDefault, ShouldBeTrue)
So(nt.Settings, ShouldResemble, map[string]interface{}{
require.Equal(t, nt.Name, "default-slack-notification")
require.Equal(t, nt.Type, "slack")
require.Equal(t, nt.OrgID, int64(2))
require.Equal(t, nt.UID, "notifier1")
require.True(t, nt.IsDefault)
require.Equal(t, nt.Settings, map[string]interface{}{
"recipient": "XXX", "token": "xoxb", "uploadImage": true, "url": "https://slack.com",
})
So(nt.SecureSettings, ShouldResemble, map[string]string{
require.Equal(t, nt.SecureSettings, map[string]string{
"token": "xoxbsecure", "url": "https://slack.com/secure",
})
So(nt.SendReminder, ShouldBeTrue)
So(nt.Frequency, ShouldEqual, "1h")
require.True(t, nt.SendReminder)
require.Equal(t, nt.Frequency, "1h")
nt = nts[1]
So(nt.Name, ShouldEqual, "another-not-default-notification")
So(nt.Type, ShouldEqual, "email")
So(nt.OrgID, ShouldEqual, 3)
So(nt.UID, ShouldEqual, "notifier2")
So(nt.IsDefault, ShouldBeFalse)
require.Equal(t, nt.Name, "another-not-default-notification")
require.Equal(t, nt.Type, "email")
require.Equal(t, nt.OrgID, int64(3))
require.Equal(t, nt.UID, "notifier2")
require.False(t, nt.IsDefault)
nt = nts[2]
So(nt.Name, ShouldEqual, "check-unset-is_default-is-false")
So(nt.Type, ShouldEqual, "slack")
So(nt.OrgID, ShouldEqual, 3)
So(nt.UID, ShouldEqual, "notifier3")
So(nt.IsDefault, ShouldBeFalse)
require.Equal(t, nt.Name, "check-unset-is_default-is-false")
require.Equal(t, nt.Type, "slack")
require.Equal(t, nt.OrgID, int64(3))
require.Equal(t, nt.UID, "notifier3")
require.False(t, nt.IsDefault)
nt = nts[3]
So(nt.Name, ShouldEqual, "Added notification with whitespaces in name")
So(nt.Type, ShouldEqual, "email")
So(nt.UID, ShouldEqual, "notifier4")
So(nt.OrgID, ShouldEqual, 3)
require.Equal(t, nt.Name, "Added notification with whitespaces in name")
require.Equal(t, nt.Type, "email")
require.Equal(t, nt.UID, "notifier4")
require.Equal(t, nt.OrgID, int64(3))
deleteNts := ntCfg.DeleteNotifications
So(len(deleteNts), ShouldEqual, 4)
require.Equal(t, len(deleteNts), 4)
deleteNt := deleteNts[0]
So(deleteNt.Name, ShouldEqual, "default-slack-notification")
So(deleteNt.UID, ShouldEqual, "notifier1")
So(deleteNt.OrgID, ShouldEqual, 2)
require.Equal(t, deleteNt.Name, "default-slack-notification")
require.Equal(t, deleteNt.UID, "notifier1")
require.Equal(t, deleteNt.OrgID, int64(2))
deleteNt = deleteNts[1]
So(deleteNt.Name, ShouldEqual, "deleted-notification-without-orgId")
So(deleteNt.OrgID, ShouldEqual, 1)
So(deleteNt.UID, ShouldEqual, "notifier2")
require.Equal(t, deleteNt.Name, "deleted-notification-without-orgId")
require.Equal(t, deleteNt.OrgID, int64(1))
require.Equal(t, deleteNt.UID, "notifier2")
deleteNt = deleteNts[2]
So(deleteNt.Name, ShouldEqual, "deleted-notification-with-0-orgId")
So(deleteNt.OrgID, ShouldEqual, 1)
So(deleteNt.UID, ShouldEqual, "notifier3")
require.Equal(t, deleteNt.Name, "deleted-notification-with-0-orgId")
require.Equal(t, deleteNt.OrgID, int64(1))
require.Equal(t, deleteNt.UID, "notifier3")
deleteNt = deleteNts[3]
So(deleteNt.Name, ShouldEqual, "Deleted notification with whitespaces in name")
So(deleteNt.OrgID, ShouldEqual, 1)
So(deleteNt.UID, ShouldEqual, "notifier4")
require.Equal(t, deleteNt.Name, "Deleted notification with whitespaces in name")
require.Equal(t, deleteNt.OrgID, int64(1))
require.Equal(t, deleteNt.UID, "notifier4")
})
Convey("One configured notification", func() {
Convey("no notification in database", func() {
t.Run("One configured notification", func(t *testing.T) {
t.Run("no notification in database", func(t *testing.T) {
setup()
dc := newNotificationProvisioner(ossencryption.ProvideService(), logger)
err := dc.applyChanges(twoNotificationsConfig)
@ -140,12 +146,13 @@ func TestNotificationAsConfig(t *testing.T) {
}
notificationsQuery := models.GetAllAlertNotificationsQuery{OrgId: 1}
err = sqlStore.GetAllAlertNotifications(&notificationsQuery)
So(err, ShouldBeNil)
So(notificationsQuery.Result, ShouldNotBeNil)
So(len(notificationsQuery.Result), ShouldEqual, 2)
require.NoError(t, err)
require.NotNil(t, notificationsQuery.Result)
require.Equal(t, len(notificationsQuery.Result), 2)
})
Convey("One notification in database with same name and uid", func() {
t.Run("One notification in database with same name and uid", func(t *testing.T) {
setup()
existingNotificationCmd := models.CreateAlertNotificationCommand{
Name: "channel1",
OrgId: 1,
@ -153,56 +160,58 @@ func TestNotificationAsConfig(t *testing.T) {
Type: "slack",
}
err := sqlStore.CreateAlertNotificationCommand(&existingNotificationCmd)
So(err, ShouldBeNil)
So(existingNotificationCmd.Result, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, existingNotificationCmd.Result)
notificationsQuery := models.GetAllAlertNotificationsQuery{OrgId: 1}
err = sqlStore.GetAllAlertNotifications(&notificationsQuery)
So(err, ShouldBeNil)
So(notificationsQuery.Result, ShouldNotBeNil)
So(len(notificationsQuery.Result), ShouldEqual, 1)
require.NoError(t, err)
require.NotNil(t, notificationsQuery.Result)
require.Equal(t, len(notificationsQuery.Result), 1)
Convey("should update one notification", func() {
t.Run("should update one notification", func(t *testing.T) {
dc := newNotificationProvisioner(ossencryption.ProvideService(), logger)
err = dc.applyChanges(twoNotificationsConfig)
if err != nil {
t.Fatalf("applyChanges return an error %v", err)
}
err = sqlStore.GetAllAlertNotifications(&notificationsQuery)
So(err, ShouldBeNil)
So(notificationsQuery.Result, ShouldNotBeNil)
So(len(notificationsQuery.Result), ShouldEqual, 2)
require.NoError(t, err)
require.NotNil(t, notificationsQuery.Result)
require.Equal(t, len(notificationsQuery.Result), 2)
nts := notificationsQuery.Result
nt1 := nts[0]
So(nt1.Type, ShouldEqual, "email")
So(nt1.Name, ShouldEqual, "channel1")
So(nt1.Uid, ShouldEqual, "notifier1")
require.Equal(t, nt1.Type, "email")
require.Equal(t, nt1.Name, "channel1")
require.Equal(t, nt1.Uid, "notifier1")
nt2 := nts[1]
So(nt2.Type, ShouldEqual, "slack")
So(nt2.Name, ShouldEqual, "channel2")
So(nt2.Uid, ShouldEqual, "notifier2")
require.Equal(t, nt2.Type, "slack")
require.Equal(t, nt2.Name, "channel2")
require.Equal(t, nt2.Uid, "notifier2")
})
})
Convey("Two notifications with is_default", func() {
t.Run("Two notifications with is_default", func(t *testing.T) {
setup()
dc := newNotificationProvisioner(ossencryption.ProvideService(), logger)
err := dc.applyChanges(doubleNotificationsConfig)
Convey("should both be inserted", func() {
So(err, ShouldBeNil)
t.Run("should both be inserted", func(t *testing.T) {
require.NoError(t, err)
notificationsQuery := models.GetAllAlertNotificationsQuery{OrgId: 1}
err = sqlStore.GetAllAlertNotifications(&notificationsQuery)
So(err, ShouldBeNil)
So(notificationsQuery.Result, ShouldNotBeNil)
So(len(notificationsQuery.Result), ShouldEqual, 2)
require.NoError(t, err)
require.NotNil(t, notificationsQuery.Result)
require.Equal(t, len(notificationsQuery.Result), 2)
So(notificationsQuery.Result[0].IsDefault, ShouldBeTrue)
So(notificationsQuery.Result[1].IsDefault, ShouldBeTrue)
require.True(t, notificationsQuery.Result[0].IsDefault)
require.True(t, notificationsQuery.Result[1].IsDefault)
})
})
})
Convey("Two configured notification", func() {
Convey("two other notifications in database", func() {
t.Run("Two configured notification", func(t *testing.T) {
t.Run("two other notifications in database", func(t *testing.T) {
setup()
existingNotificationCmd := models.CreateAlertNotificationCommand{
Name: "channel0",
OrgId: 1,
@ -210,7 +219,7 @@ func TestNotificationAsConfig(t *testing.T) {
Type: "slack",
}
err := sqlStore.CreateAlertNotificationCommand(&existingNotificationCmd)
So(err, ShouldBeNil)
require.NoError(t, err)
existingNotificationCmd = models.CreateAlertNotificationCommand{
Name: "channel3",
OrgId: 1,
@ -218,15 +227,15 @@ func TestNotificationAsConfig(t *testing.T) {
Type: "slack",
}
err = sqlStore.CreateAlertNotificationCommand(&existingNotificationCmd)
So(err, ShouldBeNil)
require.NoError(t, err)
notificationsQuery := models.GetAllAlertNotificationsQuery{OrgId: 1}
err = sqlStore.GetAllAlertNotifications(&notificationsQuery)
So(err, ShouldBeNil)
So(notificationsQuery.Result, ShouldNotBeNil)
So(len(notificationsQuery.Result), ShouldEqual, 2)
require.NoError(t, err)
require.NotNil(t, notificationsQuery.Result)
require.Equal(t, len(notificationsQuery.Result), 2)
Convey("should have two new notifications", func() {
t.Run("should have two new notifications", func(t *testing.T) {
dc := newNotificationProvisioner(ossencryption.ProvideService(), logger)
err := dc.applyChanges(twoNotificationsConfig)
if err != nil {
@ -234,22 +243,23 @@ func TestNotificationAsConfig(t *testing.T) {
}
notificationsQuery = models.GetAllAlertNotificationsQuery{OrgId: 1}
err = sqlStore.GetAllAlertNotifications(&notificationsQuery)
So(err, ShouldBeNil)
So(notificationsQuery.Result, ShouldNotBeNil)
So(len(notificationsQuery.Result), ShouldEqual, 4)
require.NoError(t, err)
require.NotNil(t, notificationsQuery.Result)
require.Equal(t, len(notificationsQuery.Result), 4)
})
})
})
Convey("Can read correct properties with orgName instead of orgId", func() {
t.Run("Can read correct properties with orgName instead of orgId", func(t *testing.T) {
setup()
existingOrg1 := models.GetOrgByNameQuery{Name: "Main Org. 1"}
err := sqlstore.GetOrgByName(&existingOrg1)
So(err, ShouldBeNil)
So(existingOrg1.Result, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, existingOrg1.Result)
existingOrg2 := models.GetOrgByNameQuery{Name: "Main Org. 2"}
err = sqlstore.GetOrgByName(&existingOrg2)
So(err, ShouldBeNil)
So(existingOrg2.Result, ShouldNotBeNil)
require.NoError(t, err)
require.NotNil(t, existingOrg2.Result)
existingNotificationCmd := models.CreateAlertNotificationCommand{
Name: "default-notification-delete",
@ -258,7 +268,7 @@ func TestNotificationAsConfig(t *testing.T) {
Type: "slack",
}
err = sqlStore.CreateAlertNotificationCommand(&existingNotificationCmd)
So(err, ShouldBeNil)
require.NoError(t, err)
dc := newNotificationProvisioner(ossencryption.ProvideService(), logger)
err = dc.applyChanges(correctPropertiesWithOrgName)
@ -268,29 +278,31 @@ func TestNotificationAsConfig(t *testing.T) {
notificationsQuery := models.GetAllAlertNotificationsQuery{OrgId: existingOrg2.Result.Id}
err = sqlStore.GetAllAlertNotifications(&notificationsQuery)
So(err, ShouldBeNil)
So(notificationsQuery.Result, ShouldNotBeNil)
So(len(notificationsQuery.Result), ShouldEqual, 1)
require.NoError(t, err)
require.NotNil(t, notificationsQuery.Result)
require.Equal(t, len(notificationsQuery.Result), 1)
nt := notificationsQuery.Result[0]
So(nt.Name, ShouldEqual, "default-notification-create")
So(nt.OrgId, ShouldEqual, existingOrg2.Result.Id)
require.Equal(t, nt.Name, "default-notification-create")
require.Equal(t, nt.OrgId, existingOrg2.Result.Id)
})
Convey("Config doesn't contain required field", func() {
t.Run("Config doesn't contain required field", func(t *testing.T) {
setup()
dc := newNotificationProvisioner(ossencryption.ProvideService(), logger)
err := dc.applyChanges(noRequiredFields)
So(err, ShouldNotBeNil)
require.NotNil(t, err)
errString := err.Error()
So(errString, ShouldContainSubstring, "Deleted alert notification item 1 in configuration doesn't contain required field uid")
So(errString, ShouldContainSubstring, "Deleted alert notification item 2 in configuration doesn't contain required field name")
So(errString, ShouldContainSubstring, "Added alert notification item 1 in configuration doesn't contain required field name")
So(errString, ShouldContainSubstring, "Added alert notification item 2 in configuration doesn't contain required field uid")
require.Contains(t, errString, "Deleted alert notification item 1 in configuration doesn't contain required field uid")
require.Contains(t, errString, "Deleted alert notification item 2 in configuration doesn't contain required field name")
require.Contains(t, errString, "Added alert notification item 1 in configuration doesn't contain required field name")
require.Contains(t, errString, "Added alert notification item 2 in configuration doesn't contain required field uid")
})
Convey("Empty yaml file", func() {
Convey("should have not changed repo", func() {
t.Run("Empty yaml file", func(t *testing.T) {
t.Run("should have not changed repo", func(t *testing.T) {
setup()
dc := newNotificationProvisioner(ossencryption.ProvideService(), logger)
err := dc.applyChanges(emptyFile)
if err != nil {
@ -298,22 +310,22 @@ func TestNotificationAsConfig(t *testing.T) {
}
notificationsQuery := models.GetAllAlertNotificationsQuery{OrgId: 1}
err = sqlStore.GetAllAlertNotifications(&notificationsQuery)
So(err, ShouldBeNil)
So(notificationsQuery.Result, ShouldBeEmpty)
require.NoError(t, err)
require.Empty(t, notificationsQuery.Result)
})
})
Convey("Broken yaml should return error", func() {
t.Run("Broken yaml should return error", func(t *testing.T) {
reader := &configReader{
encryptionService: ossencryption.ProvideService(),
log: log.New("test logger"),
}
_, err := reader.readConfig(brokenYaml)
So(err, ShouldNotBeNil)
require.NotNil(t, err)
})
Convey("Skip invalid directory", func() {
t.Run("Skip invalid directory", func(t *testing.T) {
cfgProvider := &configReader{
encryptionService: ossencryption.ProvideService(),
log: log.New("test logger"),
@ -323,27 +335,27 @@ func TestNotificationAsConfig(t *testing.T) {
if err != nil {
t.Fatalf("readConfig return an error %v", err)
}
So(len(cfg), ShouldEqual, 0)
require.Equal(t, len(cfg), 0)
})
Convey("Unknown notifier should return error", func() {
t.Run("Unknown notifier should return error", func(t *testing.T) {
cfgProvider := &configReader{
encryptionService: ossencryption.ProvideService(),
log: log.New("test logger"),
}
_, err := cfgProvider.readConfig(unknownNotifier)
So(err, ShouldNotBeNil)
So(err.Error(), ShouldEqual, `unsupported notification type "nonexisting"`)
require.NotNil(t, err)
require.Equal(t, err.Error(), `unsupported notification type "nonexisting"`)
})
Convey("Read incorrect properties", func() {
t.Run("Read incorrect properties", func(t *testing.T) {
cfgProvider := &configReader{
encryptionService: ossencryption.ProvideService(),
log: log.New("test logger"),
}
_, err := cfgProvider.readConfig(incorrectSettings)
So(err, ShouldNotBeNil)
So(err.Error(), ShouldEqual, "alert validation error: token must be specified when using the Slack chat API")
require.NotNil(t, err)
require.Equal(t, err.Error(), "alert validation error: token must be specified when using the Slack chat API")
})
})
}

@ -5,25 +5,26 @@ import (
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/sqlstore"
. "github.com/smartystreets/goconvey/convey"
"github.com/stretchr/testify/require"
)
func TestCheckOrgExists(t *testing.T) {
Convey("with default org in database", t, func() {
t.Run("with default org in database", func(t *testing.T) {
sqlstore.InitTestDB(t)
defaultOrg := models.CreateOrgCommand{Name: "Main Org."}
err := sqlstore.CreateOrg(&defaultOrg)
So(err, ShouldBeNil)
require.NoError(t, err)
Convey("default org exists", func() {
t.Run("default org exists", func(t *testing.T) {
err := CheckOrgExists(defaultOrg.Result.Id)
So(err, ShouldBeNil)
require.NoError(t, err)
})
Convey("other org doesn't exist", func() {
t.Run("other org doesn't exist", func(t *testing.T) {
err := CheckOrgExists(defaultOrg.Result.Id + 1)
So(err, ShouldEqual, models.ErrOrgNotFound)
require.Equal(t, err, models.ErrOrgNotFound)
})
})
}

@ -8,132 +8,140 @@ import (
"testing"
"github.com/grafana/grafana/pkg/setting"
"gopkg.in/ini.v1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
. "github.com/smartystreets/goconvey/convey"
"gopkg.in/ini.v1"
"gopkg.in/yaml.v2"
)
func TestValues(t *testing.T) {
Convey("Values", t, func() {
t.Run("Values", func(t *testing.T) {
err := os.Setenv("INT", "1")
So(err, ShouldBeNil)
require.NoError(t, err)
err = os.Setenv("STRING", "test")
So(err, ShouldBeNil)
require.NoError(t, err)
err = os.Setenv("EMPTYSTRING", "")
So(err, ShouldBeNil)
require.NoError(t, err)
err = os.Setenv("BOOL", "true")
So(err, ShouldBeNil)
require.NoError(t, err)
defer func() {
err := os.Unsetenv("INT")
require.NoError(t, err)
err = os.Unsetenv("STRING")
require.NoError(t, err)
err = os.Unsetenv("EMPTYSTRING")
require.NoError(t, err)
err = os.Unsetenv("BOOL")
require.NoError(t, err)
}()
Convey("IntValue", func() {
t.Run("IntValue", func(t *testing.T) {
type Data struct {
Val IntValue `yaml:"val"`
}
d := &Data{}
Convey("Should unmarshal simple number", func() {
unmarshalingTest(`val: 1`, d)
So(d.Val.Value(), ShouldEqual, 1)
So(d.Val.Raw, ShouldEqual, "1")
t.Run("Should unmarshal simple number", func(t *testing.T) {
unmarshalingTest(t, `val: 1`, d)
require.Equal(t, d.Val.Value(), 1)
require.Equal(t, d.Val.Raw, "1")
})
Convey("Should unmarshal env var", func() {
unmarshalingTest(`val: $INT`, d)
So(d.Val.Value(), ShouldEqual, 1)
So(d.Val.Raw, ShouldEqual, "$INT")
t.Run("Should unmarshal env var", func(t *testing.T) {
unmarshalingTest(t, `val: $INT`, d)
require.Equal(t, d.Val.Value(), 1)
require.Equal(t, d.Val.Raw, "$INT")
})
Convey("Should ignore empty value", func() {
unmarshalingTest(`val: `, d)
So(d.Val.Value(), ShouldEqual, 0)
So(d.Val.Raw, ShouldEqual, "")
t.Run("Should ignore empty value", func(t *testing.T) {
unmarshalingTest(t, `val: `, d)
require.Equal(t, d.Val.Value(), 0)
require.Equal(t, d.Val.Raw, "")
})
})
Convey("StringValue", func() {
t.Run("StringValue", func(t *testing.T) {
type Data struct {
Val StringValue `yaml:"val"`
}
d := &Data{}
Convey("Should unmarshal simple string", func() {
unmarshalingTest(`val: test`, d)
So(d.Val.Value(), ShouldEqual, "test")
So(d.Val.Raw, ShouldEqual, "test")
t.Run("Should unmarshal simple string", func(t *testing.T) {
unmarshalingTest(t, `val: test`, d)
require.Equal(t, d.Val.Value(), "test")
require.Equal(t, d.Val.Raw, "test")
})
Convey("Should unmarshal env var", func() {
unmarshalingTest(`val: $STRING`, d)
So(d.Val.Value(), ShouldEqual, "test")
So(d.Val.Raw, ShouldEqual, "$STRING")
t.Run("Should unmarshal env var", func(t *testing.T) {
unmarshalingTest(t, `val: $STRING`, d)
require.Equal(t, d.Val.Value(), "test")
require.Equal(t, d.Val.Raw, "$STRING")
})
Convey("Should ignore empty value", func() {
unmarshalingTest(`val: `, d)
So(d.Val.Value(), ShouldEqual, "")
So(d.Val.Raw, ShouldEqual, "")
t.Run("Should ignore empty value", func(t *testing.T) {
unmarshalingTest(t, `val: `, d)
require.Equal(t, d.Val.Value(), "")
require.Equal(t, d.Val.Raw, "")
})
Convey("empty var should have empty value", func() {
unmarshalingTest(`val: $EMPTYSTRING`, d)
So(d.Val.Value(), ShouldEqual, "")
So(d.Val.Raw, ShouldEqual, "$EMPTYSTRING")
t.Run("empty var should have empty value", func(t *testing.T) {
unmarshalingTest(t, `val: $EMPTYSTRING`, d)
require.Equal(t, d.Val.Value(), "")
require.Equal(t, d.Val.Raw, "$EMPTYSTRING")
})
Convey("$$ should be a literal $", func() {
unmarshalingTest(`val: $$`, d)
So(d.Val.Value(), ShouldEqual, "$")
So(d.Val.Raw, ShouldEqual, "$$")
t.Run("$$ should be a literal $", func(t *testing.T) {
unmarshalingTest(t, `val: $$`, d)
require.Equal(t, d.Val.Value(), "$")
require.Equal(t, d.Val.Raw, "$$")
})
Convey("$$ should be a literal $ and not expanded within a string", func() {
unmarshalingTest(`val: mY,Passwo$$rd`, d)
So(d.Val.Value(), ShouldEqual, "mY,Passwo$rd")
So(d.Val.Raw, ShouldEqual, "mY,Passwo$$rd")
t.Run("$$ should be a literal $ and not expanded within a string", func(t *testing.T) {
unmarshalingTest(t, `val: mY,Passwo$$rd`, d)
require.Equal(t, d.Val.Value(), "mY,Passwo$rd")
require.Equal(t, d.Val.Raw, "mY,Passwo$$rd")
})
})
Convey("BoolValue", func() {
t.Run("BoolValue", func(t *testing.T) {
type Data struct {
Val BoolValue `yaml:"val"`
}
d := &Data{}
Convey("Should unmarshal bool value", func() {
unmarshalingTest(`val: true`, d)
So(d.Val.Value(), ShouldBeTrue)
So(d.Val.Raw, ShouldEqual, "true")
t.Run("Should unmarshal bool value", func(t *testing.T) {
unmarshalingTest(t, `val: true`, d)
require.True(t, d.Val.Value())
require.Equal(t, d.Val.Raw, "true")
})
Convey("Should unmarshal explicit string", func() {
unmarshalingTest(`val: "true"`, d)
So(d.Val.Value(), ShouldBeTrue)
So(d.Val.Raw, ShouldEqual, "true")
t.Run("Should unmarshal explicit string", func(t *testing.T) {
unmarshalingTest(t, `val: "true"`, d)
require.True(t, d.Val.Value())
require.Equal(t, d.Val.Raw, "true")
})
Convey("Should unmarshal env var", func() {
unmarshalingTest(`val: $BOOL`, d)
So(d.Val.Value(), ShouldBeTrue)
So(d.Val.Raw, ShouldEqual, "$BOOL")
t.Run("Should unmarshal env var", func(t *testing.T) {
unmarshalingTest(t, `val: $BOOL`, d)
require.True(t, d.Val.Value())
require.Equal(t, d.Val.Raw, "$BOOL")
})
Convey("Should ignore empty value", func() {
unmarshalingTest(`val: `, d)
So(d.Val.Value(), ShouldBeFalse)
So(d.Val.Raw, ShouldEqual, "")
t.Run("Should ignore empty value", func(t *testing.T) {
unmarshalingTest(t, `val: `, d)
require.False(t, d.Val.Value())
require.Equal(t, d.Val.Raw, "")
})
})
Convey("JSONValue", func() {
t.Run("JSONValue", func(t *testing.T) {
type Data struct {
Val JSONValue `yaml:"val"`
}
d := &Data{}
Convey("Should unmarshal variable nesting", func() {
t.Run("Should unmarshal variable nesting", func(t *testing.T) {
doc := `
val:
one: 1
@ -153,10 +161,10 @@ func TestValues(t *testing.T) {
anchor: &label $INT
anchored: *label
`
unmarshalingTest(doc, d)
unmarshalingTest(t, doc, d)
type stringMap = map[string]interface{}
So(d.Val.Value(), ShouldResemble, stringMap{
require.Equal(t, d.Val.Value(), stringMap{
"one": 1,
"two": "test",
"three": []interface{}{
@ -183,7 +191,7 @@ func TestValues(t *testing.T) {
"anchored": "1",
})
So(d.Val.Raw, ShouldResemble, stringMap{
require.Equal(t, d.Val.Raw, stringMap{
"one": 1,
"two": "$STRING",
"three": []interface{}{
@ -212,13 +220,13 @@ func TestValues(t *testing.T) {
})
})
Convey("StringMapValue", func() {
t.Run("StringMapValue", func(t *testing.T) {
type Data struct {
Val StringMapValue `yaml:"val"`
}
d := &Data{}
Convey("Should unmarshal mapping", func() {
t.Run("Should unmarshal mapping", func(t *testing.T) {
doc := `
val:
one: 1
@ -226,15 +234,15 @@ func TestValues(t *testing.T) {
three: $STRING
four: true
`
unmarshalingTest(doc, d)
So(d.Val.Value(), ShouldResemble, map[string]string{
unmarshalingTest(t, doc, d)
require.Equal(t, d.Val.Value(), map[string]string{
"one": "1",
"two": "test string",
"three": "test",
"four": "true",
})
So(d.Val.Raw, ShouldResemble, map[string]string{
require.Equal(t, d.Val.Raw, map[string]string{
"one": "1",
"two": "test string",
"three": "$STRING",
@ -242,23 +250,12 @@ func TestValues(t *testing.T) {
})
})
})
Reset(func() {
err := os.Unsetenv("INT")
So(err, ShouldBeNil)
err = os.Unsetenv("STRING")
So(err, ShouldBeNil)
err = os.Unsetenv("EMPTYSTRING")
So(err, ShouldBeNil)
err = os.Unsetenv("BOOL")
So(err, ShouldBeNil)
})
})
}
func unmarshalingTest(document string, out interface{}) {
func unmarshalingTest(t *testing.T, document string, out interface{}) {
err := yaml.Unmarshal([]byte(document), out)
So(err, ShouldBeNil)
require.NoError(t, err)
}
func TestValues_readFile(t *testing.T) {

Loading…
Cancel
Save