// Copyright (c) Abstract Machines // SPDX-License-Identifier: Apache-2.0 package provision_test import ( "fmt" "os" "testing" "github.com/absmach/magistrala/provision" "github.com/absmach/supermq/channels" "github.com/absmach/supermq/clients" "github.com/absmach/supermq/pkg/connections" "github.com/absmach/supermq/pkg/errors" "github.com/pelletier/go-toml" "github.com/stretchr/testify/assert" ) var ( validConfig = provision.Config{ Server: provision.ServiceConf{ Port: "9016", LogLevel: "info", TLS: false, }, Bootstrap: provision.Bootstrap{ X509Provision: true, Provision: true, AutoWhiteList: true, Content: map[string]any{ "test": "test", }, }, Clients: []clients.Client{ { ID: "1234567890", Name: "test", Tags: []string{"test"}, Metadata: map[string]any{ "test": "test", }, PrivateMetadata: clients.Metadata{}, Actions: []string{}, AccessProviderRoleActions: []string{}, ConnectionTypes: []connections.ConnType{}, }, }, Channels: []channels.Channel{ { ID: "1234567890", Name: "test", Tags: []string{"test"}, Metadata: map[string]any{ "test": "test", }, Actions: []string{}, AccessProviderRoleActions: []string{}, ConnectionTypes: []connections.ConnType{}, }, }, Cert: provision.Cert{}, SendTelemetry: true, InstanceID: "1234567890", } validConfigFile = "./config.toml" invalidConfig = provision.Config{ Bootstrap: provision.Bootstrap{ Content: map[string]any{ "invalid": make(chan int), }, }, } invalidConfigFile = "./invalid.toml" ) func createInvalidConfigFile() error { config := map[string]any{ "invalid": "invalid", } b, err := toml.Marshal(config) if err != nil { return err } f, err := os.Create(invalidConfigFile) if err != nil { return err } if _, err = f.Write(b); err != nil { return err } return nil } func createValidConfigFile() error { b, err := toml.Marshal(validConfig) if err != nil { return err } f, err := os.Create(validConfigFile) if err != nil { return err } if _, err = f.Write(b); err != nil { return err } return nil } func TestSave(t *testing.T) { cases := []struct { desc string cfg provision.Config file string err error }{ { desc: "save valid config", cfg: validConfig, file: validConfigFile, err: nil, }, { desc: "save valid config with empty file name", cfg: validConfig, file: "", err: errors.ErrEmptyPath, }, { desc: "save empty config with valid config file", cfg: provision.Config{}, file: validConfigFile, err: nil, }, { desc: "save empty config with empty file name", cfg: provision.Config{}, file: "", err: errors.ErrEmptyPath, }, { desc: "save invalid config", cfg: invalidConfig, file: invalidConfigFile, err: errors.New("failed to read config file"), }, } for _, c := range cases { t.Run(c.desc, func(t *testing.T) { err := provision.Save(c.cfg, c.file) assert.True(t, errors.Contains(err, c.err), fmt.Sprintf("expected: %v, got: %v", c.err, err)) if err == nil { defer func() { if c.file != "" { err := os.Remove(c.file) assert.NoError(t, err) } }() cfg, err := provision.Read(c.file) if c.cfg.Bootstrap.Content == nil { c.cfg.Bootstrap.Content = map[string]any{} } assert.Equal(t, c.err, err) assert.Equal(t, c.cfg, cfg) } }) } } func TestRead(t *testing.T) { err := createInvalidConfigFile() assert.NoError(t, err) err = createValidConfigFile() assert.NoError(t, err) t.Cleanup(func() { err := os.Remove(invalidConfigFile) assert.NoError(t, err) err = os.Remove(validConfigFile) assert.NoError(t, err) }) cases := []struct { desc string file string cfg provision.Config err error }{ { desc: "read valid config", file: validConfigFile, cfg: validConfig, err: nil, }, { desc: "read invalid config", file: invalidConfigFile, cfg: invalidConfig, err: nil, }, { desc: "read empty config", file: "", cfg: provision.Config{}, err: errors.New("failed to read config file"), }, } for _, c := range cases { t.Run(c.desc, func(t *testing.T) { cfg, err := provision.Read(c.file) if c.desc == "read invalid config" { c.cfg.Bootstrap.Content = nil } assert.True(t, errors.Contains(err, c.err), fmt.Sprintf("expected: %v, got: %v", c.err, err)) assert.Equal(t, c.cfg, cfg) }) } }