pkg.re/essentialkaos/ek.10@v12.41.0+incompatible/knf/knf_test.go (about)

     1  package knf
     2  
     3  // ////////////////////////////////////////////////////////////////////////////////// //
     4  //                                                                                    //
     5  //                         Copyright (c) 2022 ESSENTIAL KAOS                          //
     6  //      Apache License, Version 2.0 <https://www.apache.org/licenses/LICENSE-2.0>     //
     7  //                                                                                    //
     8  // ////////////////////////////////////////////////////////////////////////////////// //
     9  
    10  import (
    11  	"fmt"
    12  	"io/ioutil"
    13  	"os"
    14  	"strings"
    15  	"sync"
    16  	"testing"
    17  	"time"
    18  
    19  	check "pkg.re/essentialkaos/check.v1"
    20  )
    21  
    22  // ////////////////////////////////////////////////////////////////////////////////// //
    23  
    24  const _CONFIG_DATA = `
    25      [formating]
    26  test1:      1
    27              test2:2
    28  
    29  		test3: 3 
    30  
    31  [string]
    32    test1: test
    33    test2: true
    34    test3: 4500
    35    test4: !$%^&
    36    test5: long long long long text for test
    37    test6: 
    38  
    39  [boolean]
    40    test1: true
    41    test2: false
    42    test3: 0
    43    test4: 1
    44    test5:
    45    test6: example for test
    46    test7: no
    47  
    48  [integer]
    49    test1: 1
    50    test2: -5
    51    test3: 10000000
    52    test4: A
    53    test5: 0xFF
    54    test6: 123.4
    55    test7: 123.456789
    56    test8: 0xZZYY
    57    test9: ABCD
    58  
    59  [file-mode]
    60    test1: 644
    61    test2: 0644
    62    test3: 0
    63    test4: ABC
    64    test5: true
    65  
    66  [duration]
    67  	test1: 0
    68  	test2: 60
    69  	test3: ABC
    70  	test4: true
    71  
    72  [comment]
    73    test1: 100
    74    # test2: 100
    75  
    76  [macro]
    77    test1: 100
    78    test2: {macro:test1}.50
    79    test3: Value is {macro:test2}
    80    test4: "{macro:test3}"
    81    test5: {ABC}
    82    test6: {}
    83  
    84  [k]
    85    t: 1
    86  `
    87  
    88  const _CONFIG_MALF_DATA = `
    89    test1: 123
    90    test2: 111
    91  `
    92  
    93  const (
    94  	_CONFIG_FILE_NAME           = "knf-config-test.conf"
    95  	_CONFIG_EMPTY_FILE_NAME     = "knf-config-test-empty.conf"
    96  	_CONFIG_MALFORMED_FILE_NAME = "knf-config-test-malf.conf"
    97  )
    98  
    99  // ////////////////////////////////////////////////////////////////////////////////// //
   100  
   101  type KNFSuite struct {
   102  	ConfigPath            string
   103  	EmptyConfigPath       string
   104  	MalformedConfigPath   string
   105  	NonReadableConfigPath string
   106  }
   107  
   108  // ////////////////////////////////////////////////////////////////////////////////// //
   109  
   110  var _ = check.Suite(&KNFSuite{})
   111  
   112  // ////////////////////////////////////////////////////////////////////////////////// //
   113  
   114  func Test(t *testing.T) {
   115  	check.TestingT(t)
   116  }
   117  
   118  // ////////////////////////////////////////////////////////////////////////////////// //
   119  
   120  func (s *KNFSuite) SetUpSuite(c *check.C) {
   121  	tmpdir := c.MkDir()
   122  
   123  	s.ConfigPath = tmpdir + "/" + _CONFIG_FILE_NAME
   124  	s.EmptyConfigPath = tmpdir + "/" + _CONFIG_EMPTY_FILE_NAME
   125  	s.MalformedConfigPath = tmpdir + "/" + _CONFIG_MALFORMED_FILE_NAME
   126  	s.NonReadableConfigPath = "/etc/sudoers"
   127  
   128  	err := ioutil.WriteFile(s.ConfigPath, []byte(_CONFIG_DATA), 0644)
   129  
   130  	if err != nil {
   131  		c.Fatal(err.Error())
   132  	}
   133  
   134  	err = ioutil.WriteFile(s.EmptyConfigPath, []byte(""), 0644)
   135  
   136  	if err != nil {
   137  		c.Fatal(err.Error())
   138  	}
   139  
   140  	err = ioutil.WriteFile(s.MalformedConfigPath, []byte(_CONFIG_MALF_DATA), 0644)
   141  
   142  	if err != nil {
   143  		c.Fatal(err.Error())
   144  	}
   145  }
   146  
   147  func (s *KNFSuite) TestErrors(c *check.C) {
   148  	global = nil
   149  
   150  	err := Global("/_not_exists_")
   151  	c.Assert(err, check.NotNil)
   152  
   153  	err = Global(s.EmptyConfigPath)
   154  	c.Assert(err, check.NotNil)
   155  
   156  	err = Global(s.NonReadableConfigPath)
   157  	c.Assert(err, check.NotNil)
   158  
   159  	err = Global(s.MalformedConfigPath)
   160  
   161  	c.Assert(err, check.NotNil)
   162  	c.Assert(err.Error(), check.Equals, "Error at line 2: Data defined before section")
   163  
   164  	updated, err := Reload()
   165  
   166  	c.Assert(err, check.NotNil)
   167  	c.Assert(err, check.DeepEquals, ErrConfigIsNil)
   168  	c.Assert(updated, check.IsNil)
   169  
   170  	c.Assert(GetS("test"), check.Equals, "")
   171  	c.Assert(GetI("test"), check.Equals, 0)
   172  	c.Assert(GetI("test"), check.Equals, 0)
   173  	c.Assert(GetU("test"), check.Equals, uint(0))
   174  	c.Assert(GetI64("test"), check.Equals, int64(0))
   175  	c.Assert(GetU64("test"), check.Equals, uint64(0))
   176  	c.Assert(GetF("test"), check.Equals, 0.0)
   177  	c.Assert(GetB("test"), check.Equals, false)
   178  	c.Assert(GetM("test"), check.Equals, os.FileMode(0))
   179  	c.Assert(GetD("test"), check.Equals, time.Duration(0))
   180  	c.Assert(HasSection("test"), check.Equals, false)
   181  	c.Assert(HasProp("test"), check.Equals, false)
   182  	c.Assert(Sections(), check.HasLen, 0)
   183  	c.Assert(Props("test"), check.HasLen, 0)
   184  	c.Assert(Validate([]*Validator{}), check.DeepEquals, []error{ErrConfigIsNil})
   185  
   186  	config := &Config{mx: &sync.RWMutex{}}
   187  
   188  	c.Assert(config.GetS("test"), check.Equals, "")
   189  	c.Assert(config.GetI("test"), check.Equals, 0)
   190  	c.Assert(config.GetF("test"), check.Equals, 0.0)
   191  	c.Assert(config.GetB("test"), check.Equals, false)
   192  	c.Assert(config.GetM("test"), check.Equals, os.FileMode(0))
   193  	c.Assert(config.GetD("test"), check.Equals, time.Duration(0))
   194  	c.Assert(config.HasSection("test"), check.Equals, false)
   195  	c.Assert(config.HasProp("test"), check.Equals, false)
   196  	c.Assert(config.Sections(), check.HasLen, 0)
   197  	c.Assert(config.Props("test"), check.HasLen, 0)
   198  	c.Assert(config.Validate([]*Validator{}), check.HasLen, 0)
   199  
   200  	updated, err = config.Reload()
   201  
   202  	c.Assert(updated, check.IsNil)
   203  	c.Assert(err, check.NotNil)
   204  	c.Assert(err, check.DeepEquals, ErrFileNotSet)
   205  
   206  	config = &Config{file: "/_not_exists_", mx: &sync.RWMutex{}}
   207  
   208  	updated, err = config.Reload()
   209  
   210  	c.Assert(updated, check.IsNil)
   211  	c.Assert(err, check.NotNil)
   212  }
   213  
   214  func (s *KNFSuite) TestParsing(c *check.C) {
   215  	err := Global(s.ConfigPath)
   216  
   217  	c.Assert(err, check.IsNil)
   218  
   219  	_, err = Reload()
   220  
   221  	c.Assert(err, check.IsNil)
   222  }
   223  
   224  func (s *KNFSuite) TestSections(c *check.C) {
   225  	var err error
   226  
   227  	err = Global(s.ConfigPath)
   228  
   229  	c.Assert(global, check.NotNil)
   230  	c.Assert(err, check.IsNil)
   231  
   232  	sections := Sections()
   233  
   234  	c.Assert(sections, check.HasLen, 9)
   235  	c.Assert(
   236  		sections,
   237  		check.DeepEquals,
   238  		[]string{
   239  			"formating",
   240  			"string",
   241  			"boolean",
   242  			"integer",
   243  			"file-mode",
   244  			"duration",
   245  			"comment",
   246  			"macro",
   247  			"k",
   248  		},
   249  	)
   250  }
   251  
   252  func (s *KNFSuite) TestProps(c *check.C) {
   253  	var err error
   254  
   255  	err = Global(s.ConfigPath)
   256  
   257  	c.Assert(global, check.NotNil)
   258  	c.Assert(err, check.IsNil)
   259  
   260  	props := Props("file-mode")
   261  
   262  	c.Assert(props, check.HasLen, 5)
   263  	c.Assert(
   264  		props,
   265  		check.DeepEquals,
   266  		[]string{"test1", "test2", "test3", "test4", "test5"},
   267  	)
   268  }
   269  
   270  func (s *KNFSuite) TestCheckers(c *check.C) {
   271  	var err error
   272  
   273  	err = Global(s.ConfigPath)
   274  
   275  	c.Assert(global, check.NotNil)
   276  	c.Assert(err, check.IsNil)
   277  
   278  	c.Assert(HasSection("string"), check.Equals, true)
   279  	c.Assert(HasSection("strings"), check.Equals, false)
   280  
   281  	c.Assert(HasProp("string:test1"), check.Equals, true)
   282  	c.Assert(HasProp("string:test6"), check.Equals, false)
   283  	c.Assert(HasProp("strings:test6"), check.Equals, false)
   284  }
   285  
   286  func (s *KNFSuite) TestFormating(c *check.C) {
   287  	var err error
   288  
   289  	err = Global(s.ConfigPath)
   290  
   291  	c.Assert(global, check.NotNil)
   292  	c.Assert(err, check.IsNil)
   293  
   294  	c.Assert(GetI("formating:test1"), check.Equals, 1)
   295  	c.Assert(GetI("formating:test2"), check.Equals, 2)
   296  	c.Assert(GetI("formating:test3"), check.Equals, 3)
   297  }
   298  
   299  func (s *KNFSuite) TestStrings(c *check.C) {
   300  	var err error
   301  
   302  	err = Global(s.ConfigPath)
   303  
   304  	c.Assert(global, check.NotNil)
   305  	c.Assert(err, check.IsNil)
   306  
   307  	c.Assert(GetS("string:test1"), check.Equals, "test")
   308  	c.Assert(GetS("string:test2"), check.Equals, "true")
   309  	c.Assert(GetS("string:test3"), check.Equals, "4500")
   310  	c.Assert(GetS("string:test4"), check.Equals, "!$%^&")
   311  	c.Assert(GetS("string:test5"), check.Equals, "long long long long text for test")
   312  }
   313  
   314  func (s *KNFSuite) TestBoolean(c *check.C) {
   315  	var err error
   316  
   317  	err = Global(s.ConfigPath)
   318  
   319  	c.Assert(global, check.NotNil)
   320  	c.Assert(err, check.IsNil)
   321  
   322  	c.Assert(GetB("boolean:test1"), check.Equals, true)
   323  	c.Assert(GetB("boolean:test2"), check.Equals, false)
   324  	c.Assert(GetB("boolean:test3"), check.Equals, false)
   325  	c.Assert(GetB("boolean:test4"), check.Equals, true)
   326  	c.Assert(GetB("boolean:test5"), check.Equals, false)
   327  	c.Assert(GetB("boolean:test6"), check.Equals, true)
   328  	c.Assert(GetB("boolean:test7"), check.Equals, false)
   329  }
   330  
   331  func (s *KNFSuite) TestInteger(c *check.C) {
   332  	var err error
   333  
   334  	err = Global(s.ConfigPath)
   335  
   336  	c.Assert(global, check.NotNil)
   337  	c.Assert(err, check.IsNil)
   338  
   339  	c.Assert(GetI("integer:test1"), check.Equals, 1)
   340  	c.Assert(GetI("integer:test2"), check.Equals, -5)
   341  	c.Assert(GetI("integer:test3"), check.Equals, 10000000)
   342  	c.Assert(GetI("integer:test4"), check.Equals, 0)
   343  	c.Assert(GetI("integer:test5"), check.Equals, 0xFF)
   344  	c.Assert(GetF("integer:test6"), check.Equals, 123.4)
   345  	c.Assert(GetF("integer:test7"), check.Equals, 123.456789)
   346  	c.Assert(GetF("integer:test8"), check.Equals, 0.0)
   347  	c.Assert(GetI("integer:test8"), check.Equals, 0)
   348  	c.Assert(GetF("integer:test9"), check.Equals, 0.0)
   349  
   350  	c.Assert(GetU("integer:test1"), check.Equals, uint(1))
   351  	c.Assert(GetI64("integer:test1"), check.Equals, int64(1))
   352  	c.Assert(GetU64("integer:test1"), check.Equals, uint64(1))
   353  }
   354  
   355  func (s *KNFSuite) TestFileMode(c *check.C) {
   356  	var err error
   357  
   358  	err = Global(s.ConfigPath)
   359  
   360  	c.Assert(global, check.NotNil)
   361  	c.Assert(err, check.IsNil)
   362  
   363  	c.Assert(GetM("file-mode:test1"), check.Equals, os.FileMode(0644))
   364  	c.Assert(GetM("file-mode:test2"), check.Equals, os.FileMode(0644))
   365  	c.Assert(GetM("file-mode:test3"), check.Equals, os.FileMode(0))
   366  	c.Assert(GetM("file-mode:test4"), check.Equals, os.FileMode(0))
   367  	c.Assert(GetM("file-mode:test5"), check.Equals, os.FileMode(0))
   368  }
   369  
   370  func (s *KNFSuite) TestDuration(c *check.C) {
   371  	var err error
   372  
   373  	err = Global(s.ConfigPath)
   374  
   375  	c.Assert(global, check.NotNil)
   376  	c.Assert(err, check.IsNil)
   377  
   378  	c.Assert(GetD("duration:test1"), check.Equals, time.Duration(0))
   379  	c.Assert(GetD("duration:test2"), check.Equals, time.Minute)
   380  	c.Assert(GetD("duration:test3"), check.Equals, time.Duration(0))
   381  	c.Assert(GetD("duration:test4"), check.Equals, time.Duration(0))
   382  }
   383  
   384  func (s *KNFSuite) TestComments(c *check.C) {
   385  	var err error
   386  
   387  	err = Global(s.ConfigPath)
   388  
   389  	c.Assert(global, check.NotNil)
   390  	c.Assert(err, check.IsNil)
   391  
   392  	c.Assert(GetI("comment:test1"), check.Equals, 100)
   393  	c.Assert(GetI("comment:test2"), check.Not(check.Equals), 100)
   394  	c.Assert(HasProp("comment:test2"), check.Equals, false)
   395  }
   396  
   397  func (s *KNFSuite) TestMacro(c *check.C) {
   398  	var err error
   399  
   400  	err = Global(s.ConfigPath)
   401  
   402  	c.Assert(global, check.NotNil)
   403  	c.Assert(err, check.IsNil)
   404  
   405  	c.Assert(GetS("macro:test1"), check.Equals, "100")
   406  	c.Assert(GetI("macro:test1"), check.Equals, 100)
   407  	c.Assert(GetS("macro:test2"), check.Equals, "100.50")
   408  	c.Assert(GetS("macro:test3"), check.Equals, "Value is 100.50")
   409  	c.Assert(GetS("macro:test4"), check.Equals, "\"Value is 100.50\"")
   410  	c.Assert(GetS("macro:test5"), check.Equals, "{ABC}")
   411  	c.Assert(GetS("macro:test6"), check.Equals, "{}")
   412  }
   413  
   414  func (s *KNFSuite) TestNil(c *check.C) {
   415  	var nilConf *Config
   416  
   417  	c.Assert(nilConf.GetS("formating:test1"), check.Equals, "")
   418  	c.Assert(nilConf.GetI("formating:test1"), check.Equals, 0)
   419  	c.Assert(nilConf.GetF("formating:test1"), check.Equals, 0.0)
   420  	c.Assert(nilConf.GetB("formating:test1"), check.Equals, false)
   421  	c.Assert(nilConf.GetM("formating:test1"), check.Equals, os.FileMode(0))
   422  	c.Assert(nilConf.GetD("formating:test1"), check.Equals, time.Duration(0))
   423  	c.Assert(nilConf.HasSection("formating"), check.Equals, false)
   424  	c.Assert(nilConf.HasProp("formating:test1"), check.Equals, false)
   425  	c.Assert(nilConf.Sections(), check.HasLen, 0)
   426  	c.Assert(nilConf.Props("formating"), check.HasLen, 0)
   427  
   428  	_, err := nilConf.Reload()
   429  
   430  	c.Assert(err, check.NotNil)
   431  	c.Assert(err, check.DeepEquals, ErrConfigIsNil)
   432  
   433  	errs := nilConf.Validate([]*Validator{})
   434  
   435  	c.Assert(errs, check.Not(check.HasLen), 0)
   436  	c.Assert(errs, check.DeepEquals, []error{ErrConfigIsNil})
   437  }
   438  
   439  func (s *KNFSuite) TestDefault(c *check.C) {
   440  	var err error
   441  
   442  	global = nil
   443  
   444  	c.Assert(GetS("string:test100", "fail"), check.Equals, "fail")
   445  	c.Assert(GetB("boolean:test100", true), check.Equals, true)
   446  	c.Assert(GetI("integer:test100", 9999), check.Equals, 9999)
   447  	c.Assert(GetU("integer:test100", 9999), check.Equals, uint(9999))
   448  	c.Assert(GetI64("integer:test100", 9999), check.Equals, int64(9999))
   449  	c.Assert(GetU64("integer:test100", 9999), check.Equals, uint64(9999))
   450  	c.Assert(GetF("integer:test100", 123.45), check.Equals, 123.45)
   451  	c.Assert(GetM("file-mode:test100", 0755), check.Equals, os.FileMode(0755))
   452  	c.Assert(GetD("duration:test100", time.Minute), check.Equals, time.Minute)
   453  	c.Assert(GetS("string:test6", "fail"), check.Equals, "fail")
   454  
   455  	err = Global(s.ConfigPath)
   456  
   457  	c.Assert(global, check.NotNil)
   458  	c.Assert(err, check.IsNil)
   459  
   460  	c.Assert(GetS("string:test100", "fail"), check.Equals, "fail")
   461  	c.Assert(GetB("boolean:test100", true), check.Equals, true)
   462  	c.Assert(GetI("integer:test100", 9999), check.Equals, 9999)
   463  	c.Assert(GetU("integer:test100", 9999), check.Equals, uint(9999))
   464  	c.Assert(GetI64("integer:test100", 9999), check.Equals, int64(9999))
   465  	c.Assert(GetU64("integer:test100", 9999), check.Equals, uint64(9999))
   466  	c.Assert(GetF("integer:test100", 123.45), check.Equals, 123.45)
   467  	c.Assert(GetM("file-mode:test100", 0755), check.Equals, os.FileMode(0755))
   468  	c.Assert(GetD("duration:test100", time.Minute), check.Equals, time.Minute)
   469  	c.Assert(GetS("string:test6", "fail"), check.Equals, "fail")
   470  
   471  	var nc *Config
   472  
   473  	c.Assert(nc.GetS("string:test100", "fail"), check.Equals, "fail")
   474  	c.Assert(nc.GetB("boolean:test100", true), check.Equals, true)
   475  	c.Assert(nc.GetI("integer:test100", 9999), check.Equals, 9999)
   476  	c.Assert(nc.GetU("integer:test100", 9999), check.Equals, uint(9999))
   477  	c.Assert(nc.GetI64("integer:test100", 9999), check.Equals, int64(9999))
   478  	c.Assert(nc.GetU64("integer:test100", 9999), check.Equals, uint64(9999))
   479  	c.Assert(nc.GetF("integer:test100", 123.45), check.Equals, 123.45)
   480  	c.Assert(nc.GetM("file-mode:test100", 0755), check.Equals, os.FileMode(0755))
   481  	c.Assert(nc.GetD("duration:test100", time.Minute), check.Equals, time.Minute)
   482  	c.Assert(nc.GetS("string:test6", "fail"), check.Equals, "fail")
   483  }
   484  
   485  func (s *KNFSuite) TestSimpleValidator(c *check.C) {
   486  	err := Global(s.ConfigPath)
   487  
   488  	c.Assert(global, check.NotNil)
   489  	c.Assert(err, check.IsNil)
   490  
   491  	var simpleValidator = func(config *Config, prop string, value interface{}) error {
   492  		if prop == "string:test2" {
   493  			return fmt.Errorf("ERROR")
   494  		}
   495  
   496  		return nil
   497  	}
   498  
   499  	errs := Validate([]*Validator{
   500  		{"string:test2", simpleValidator, nil},
   501  	})
   502  
   503  	c.Assert(errs, check.HasLen, 1)
   504  }
   505  
   506  func (s *KNFSuite) TestKNFParserExceptions(c *check.C) {
   507  	r := strings.NewReader(`
   508  		[section]
   509  		ABCD
   510  	`)
   511  
   512  	_, err := readKNFData(r)
   513  	c.Assert(err.Error(), check.Equals, "Error at line 3: Property must have \":\" as a delimiter")
   514  
   515  	r = strings.NewReader(`
   516  		[section]
   517  		A: 1
   518  		A: 2
   519  	`)
   520  
   521  	_, err = readKNFData(r)
   522  	c.Assert(err.Error(), check.Equals, "Error at line 4: Property \"A\" defined more than once")
   523  
   524  	r = strings.NewReader(`
   525  		[section]
   526  		A: {abcd:test}
   527  	`)
   528  
   529  	_, err = readKNFData(r)
   530  	c.Assert(err.Error(), check.Equals, "Error at line 3: Unknown property {abcd:test}")
   531  }