github.com/swiftstack/ProxyFS@v0.0.0-20210203235616-4017c267d62f/conf/api_test.go (about)

     1  // Copyright (c) 2015-2021, NVIDIA CORPORATION.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package conf
     5  
     6  import (
     7  	"bytes"
     8  	"encoding/base64"
     9  	"io"
    10  	"io/ioutil"
    11  	"os"
    12  	"path/filepath"
    13  	"reflect"
    14  	"testing"
    15  	"time"
    16  
    17  	"github.com/stretchr/testify/assert"
    18  )
    19  
    20  const errnoEACCES = int(13)
    21  
    22  var tempFile1Name string
    23  var tempFile2Name string
    24  var tempFile3Name string
    25  var tempFile4Name string
    26  var tempFile5Name string
    27  var tempFile6Name string
    28  var tempFile7Name string
    29  var confStringToTest1 string
    30  var confStringToTest2 string
    31  var confStringToTest3 string
    32  
    33  func TestMain(m *testing.M) {
    34  	tempFile1, errorTempFile1 := ioutil.TempFile(os.TempDir(), "TestConfFile1_")
    35  	if nil != errorTempFile1 {
    36  		os.Exit(errnoEACCES)
    37  	}
    38  
    39  	tempFile1Name = tempFile1.Name()
    40  
    41  	io.WriteString(tempFile1, "# A comment on it's own line\n")
    42  	io.WriteString(tempFile1, "[TestNamespace:Test_-_Section]\n")
    43  	io.WriteString(tempFile1, "Test_-_Option : TestValue1,TestValue2 # A comment at the end of a line\n")
    44  
    45  	tempFile1.Close()
    46  
    47  	tempFile2, errorTempFile2 := ioutil.TempFile(os.TempDir(), "TestConfFile2_")
    48  	if nil != errorTempFile2 {
    49  		os.Remove(tempFile1Name)
    50  		os.Exit(errnoEACCES)
    51  	}
    52  
    53  	tempFile2Name = tempFile2.Name()
    54  
    55  	io.WriteString(tempFile2, "; A comment on it's own line\n")
    56  	io.WriteString(tempFile2, "[TestNamespace:Test_-_Section] ; A comment at the end of a line\n")
    57  	io.WriteString(tempFile2, "Test_-_Option =\n")
    58  
    59  	tempFile2.Close()
    60  
    61  	tempFile3, errorTempFile3 := ioutil.TempFile(os.TempDir(), "TestConfFile3_")
    62  	if nil != errorTempFile3 {
    63  		os.Remove(tempFile1Name)
    64  		os.Remove(tempFile2Name)
    65  		os.Exit(errnoEACCES)
    66  	}
    67  
    68  	tempFile3Name = tempFile3.Name()
    69  
    70  	io.WriteString(tempFile3, "[TestNamespace:Test_-_Section]\n")
    71  	io.WriteString(tempFile3, "Test_-_Option = http://Test.Value.3/ TestValue4$\tTestValue5$\n")
    72  
    73  	tempFile3.Close()
    74  
    75  	tempFile4, errorTempFile4 := ioutil.TempFile(os.TempDir(), "TestConfFile4_")
    76  	if nil != errorTempFile4 {
    77  		os.Remove(tempFile1Name)
    78  		os.Remove(tempFile2Name)
    79  		os.Remove(tempFile3Name)
    80  		os.Exit(errnoEACCES)
    81  	}
    82  
    83  	tempFile4Name = tempFile4.Name()
    84  
    85  	tempFile4.Close()
    86  
    87  	tempFile5, errorTempFile5 := ioutil.TempFile(os.TempDir(), "TestConfFile5_")
    88  	if nil != errorTempFile5 {
    89  		os.Remove(tempFile1Name)
    90  		os.Remove(tempFile2Name)
    91  		os.Remove(tempFile3Name)
    92  		os.Remove(tempFile4Name)
    93  		os.Exit(errnoEACCES)
    94  	}
    95  
    96  	tempFile5Name = tempFile5.Name()
    97  
    98  	io.WriteString(tempFile5, ".include ./"+filepath.Base(tempFile4Name)+"\n")
    99  
   100  	tempFile5.Close()
   101  
   102  	tempFile6, errorTempFile6 := ioutil.TempFile(os.TempDir(), "TestConfFile6_")
   103  	if nil != errorTempFile6 {
   104  		os.Remove(tempFile1Name)
   105  		os.Remove(tempFile2Name)
   106  		os.Remove(tempFile3Name)
   107  		os.Remove(tempFile4Name)
   108  		os.Remove(tempFile5Name)
   109  		os.Exit(errnoEACCES)
   110  	}
   111  
   112  	tempFile6Name = tempFile6.Name()
   113  
   114  	io.WriteString(tempFile6, "[TestNamespace:Test_-_Section_-_1]\n")
   115  	io.WriteString(tempFile6, "Option_-_1_-_No_-_Values  :\n")
   116  	io.WriteString(tempFile6, "Option_-_2_-_One_-_Value  : Value_-_1\n")
   117  	io.WriteString(tempFile6, "Option_-_3_-_Two_-_Values : Value_-_1, Value_-_2\n")
   118  	io.WriteString(tempFile6, "\n")
   119  	io.WriteString(tempFile6, "[TestNamespace:Test_-_Section_-_2]\n")
   120  	io.WriteString(tempFile6, "Option : Value\n")
   121  
   122  	tempFile6.Close()
   123  
   124  	tempFile7, errorTempFile7 := ioutil.TempFile(os.TempDir(), "TestConfFile7_")
   125  	if nil != errorTempFile7 {
   126  		os.Remove(tempFile1Name)
   127  		os.Remove(tempFile2Name)
   128  		os.Remove(tempFile3Name)
   129  		os.Remove(tempFile4Name)
   130  		os.Remove(tempFile5Name)
   131  		os.Remove(tempFile6Name)
   132  		os.Exit(errnoEACCES)
   133  	}
   134  
   135  	tempFile7Name = tempFile7.Name()
   136  
   137  	// Leave it empty... will be used as output file
   138  
   139  	tempFile7.Close()
   140  
   141  	confStringToTest1 = "TestNamespace:Test_-_Section.Test_-_Option = TestValue6,http://Test.Value_-_7/"
   142  	confStringToTest2 = "TestNamespace:Test_-_Section.Test_-_Option = TestValue8$,http://Test.Value_-_9/$"
   143  	confStringToTest3 = "TestNamespace:Test_-_Section.Test_-_Option ="
   144  
   145  	mRunReturn := m.Run()
   146  
   147  	os.Remove(tempFile1Name)
   148  	os.Remove(tempFile2Name)
   149  	os.Remove(tempFile3Name)
   150  	os.Remove(tempFile4Name)
   151  	os.Remove(tempFile5Name)
   152  	os.Remove(tempFile6Name)
   153  	os.Remove(tempFile7Name)
   154  
   155  	os.Exit(mRunReturn)
   156  }
   157  
   158  func TestUpdate(t *testing.T) {
   159  	var confMap = MakeConfMap()
   160  
   161  	err := confMap.UpdateFromFile(tempFile1Name)
   162  	if nil != err {
   163  		t.Fatalf("UpdateConfMapFromFile(\"%v\") returned: \"%v\"", tempFile1Name, err)
   164  	}
   165  
   166  	confMapSection, ok := confMap["TestNamespace:Test_-_Section"]
   167  	if !ok {
   168  		t.Fatalf("confMap[\"%v\"] missing", "TestNamespace:Test_-_Section")
   169  	}
   170  
   171  	confMapOption, ok := confMapSection["Test_-_Option"]
   172  	if !ok {
   173  		t.Fatalf("confMapSection[\"%v\"] missing", "Test_-_Option")
   174  	}
   175  
   176  	if 2 != len(confMapOption) {
   177  		t.Fatalf("confMapSection[\"%v\"] constains unexpected number of values (%v)", "Test_-_Option", len(confMapOption))
   178  	}
   179  
   180  	if "TestValue1" != string(confMapOption[0]) {
   181  		t.Fatalf("confMapOption != \"%v\"", "TestValue1")
   182  	}
   183  
   184  	if "TestValue2" != string(confMapOption[1]) {
   185  		t.Fatalf("confMapOption != \"%v\"", "TestValue2")
   186  	}
   187  
   188  	err = confMap.UpdateFromFile(tempFile2Name)
   189  	if nil != err {
   190  		t.Fatalf("UpdateConfMapFromFile(\"%v\") returned: \"%v\"", tempFile2Name, err)
   191  	}
   192  
   193  	confMapSection, ok = confMap["TestNamespace:Test_-_Section"]
   194  	if !ok {
   195  		t.Fatalf("confMap[\"%v\"] missing", "Test_-_Section")
   196  	}
   197  
   198  	confMapOption, ok = confMapSection["Test_-_Option"]
   199  	if !ok {
   200  		t.Fatalf("confMapSection[\"%v\"] missing", "Test_-_Option")
   201  	}
   202  
   203  	if 0 != len(confMapOption) {
   204  		t.Fatalf("confMapSection[\"%v\"] constains unexpected number of values (%v)", "Test_-_Option", len(confMapOption))
   205  	}
   206  
   207  	err = confMap.UpdateFromFile(tempFile3Name)
   208  	if nil != err {
   209  		t.Fatalf("UpdateConfMapFromFile(\"%v\") returned: \"%v\"", tempFile3Name, err)
   210  	}
   211  
   212  	confMapSection, ok = confMap["TestNamespace:Test_-_Section"]
   213  	if !ok {
   214  		t.Fatalf("confMap[\"%v\"] missing", "Test_-_Section")
   215  	}
   216  
   217  	confMapOption, ok = confMapSection["Test_-_Option"]
   218  	if !ok {
   219  		t.Fatalf("confMapSection[\"%v\"] missing", "Test_-_Option")
   220  	}
   221  
   222  	if 3 != len(confMapOption) {
   223  		t.Fatalf("confMapSection[\"%v\"] constains unexpected number of values (%v)", "Test_-_Option", len(confMapOption))
   224  	}
   225  
   226  	if "http://Test.Value.3/" != string(confMapOption[0]) {
   227  		t.Fatalf("confMapOption != \"%v\"", "http://Test.Value.3/")
   228  	}
   229  
   230  	if "TestValue4$" != string(confMapOption[1]) {
   231  		t.Fatalf("confMapOption != \"%v\"", "TestValue4$")
   232  	}
   233  
   234  	if "TestValue5$" != string(confMapOption[2]) {
   235  		t.Fatalf("confMapOption != \"%v\"", "TestValue5$")
   236  	}
   237  
   238  	err = confMap.UpdateFromString(confStringToTest1)
   239  
   240  	if nil != err {
   241  		t.Fatalf("UpdateConfMapFromString(\"%v\") returned: \"%v\"", confStringToTest1, err)
   242  	}
   243  
   244  	confMapSection, ok = confMap["TestNamespace:Test_-_Section"]
   245  	if !ok {
   246  		t.Fatalf("confMap[\"%v\"] missing", "Test_-_Section")
   247  	}
   248  
   249  	confMapOption, ok = confMapSection["Test_-_Option"]
   250  	if !ok {
   251  		t.Fatalf("confMapSection[\"%v\"] missing", "Test_-_Option")
   252  	}
   253  
   254  	if 2 != len(confMapOption) {
   255  		t.Fatalf("confMapSection[\"%v\"] constains unexpected number of values (%v)", "Test_-_Option", len(confMapOption))
   256  	}
   257  
   258  	if "TestValue6" != string(confMapOption[0]) {
   259  		t.Fatalf("confMapOption != \"%v\"", "TestValue6")
   260  	}
   261  
   262  	if "http://Test.Value_-_7/" != string(confMapOption[1]) {
   263  		t.Fatalf("confMapOption != \"%v\"", "http://Test.Value_-_7/")
   264  	}
   265  
   266  	err = confMap.UpdateFromString(confStringToTest2)
   267  
   268  	if nil != err {
   269  		t.Fatalf("UpdateConfMapFromString(\"%v\") returned: \"%v\"", confStringToTest2, err)
   270  	}
   271  
   272  	confMapSection, ok = confMap["TestNamespace:Test_-_Section"]
   273  	if !ok {
   274  		t.Fatalf("confMap[\"%v\"] missing", "Test_-_Section")
   275  	}
   276  
   277  	confMapOption, ok = confMapSection["Test_-_Option"]
   278  	if !ok {
   279  		t.Fatalf("confMapSection[\"%v\"] missing", "Test_-_Option")
   280  	}
   281  
   282  	if 2 != len(confMapOption) {
   283  		t.Fatalf("confMapSection[\"%v\"] constains unexpected number of values (%v)", "Test_-_Option", len(confMapOption))
   284  	}
   285  
   286  	if "TestValue8$" != string(confMapOption[0]) {
   287  		t.Fatalf("confMapOption != \"%v\"", "TestValue8$")
   288  	}
   289  
   290  	if "http://Test.Value_-_9/$" != string(confMapOption[1]) {
   291  		t.Fatalf("confMapOption != \"%v\"", "http://Test.Value_-_9/$")
   292  	}
   293  
   294  	err = confMap.UpdateFromString(confStringToTest3)
   295  
   296  	if nil != err {
   297  		t.Fatalf("UpdateConfMapFromString(\"%v\") returned: \"%v\"", confStringToTest3, err)
   298  	}
   299  
   300  	confMapOption, ok = confMapSection["Test_-_Option"]
   301  	if !ok {
   302  		t.Fatalf("confMapSection[\"%v\"] missing", "Test_-_Option")
   303  	}
   304  
   305  	if 0 != len(confMapOption) {
   306  		t.Fatalf("confMapSection[\"%v\"] constains unexpected number of values (%v)", "Test_-_Option", len(confMapOption))
   307  	}
   308  }
   309  
   310  func TestFromFileConstructor(t *testing.T) {
   311  	confMap, err := MakeConfMapFromFile(tempFile3Name)
   312  	if nil != err {
   313  		t.Fatalf("MakeConfMapFromFile(): expected err to be nil, got %#v", err)
   314  	}
   315  
   316  	values, err := confMap.FetchOptionValueStringSlice("TestNamespace:Test_-_Section", "Test_-_Option")
   317  	if err != nil {
   318  		t.Fatalf("FetchOptionValueStringSlice(): expected err to be nil, got %#v", err)
   319  	}
   320  	expected := "http://Test.Value.3/"
   321  	if values[0] != expected {
   322  		t.Fatalf("FetchOptionValueStringSlice(): expected %#v, got %#v", expected, values[0])
   323  	}
   324  }
   325  
   326  func TestFromFileConstructorNonexistentFile(t *testing.T) {
   327  	_, err := MakeConfMapFromFile("/does/not/exist")
   328  	expectedErr := "open /does/not/exist: no such file or directory"
   329  	if err.Error() != expectedErr {
   330  		t.Fatalf("expected err to be %#v, got %#v", expectedErr, err.Error())
   331  	}
   332  }
   333  
   334  func TestFetch(t *testing.T) {
   335  	const (
   336  		base64DecodedString              = "Now is the time"
   337  		base64DecodedStringSliceElement0 = "for all good men"
   338  		base64DecodedStringSliceElement1 = "to come to the aid of their country."
   339  	)
   340  	var (
   341  		base64EncodedString              = base64.StdEncoding.EncodeToString([]byte(base64DecodedString))
   342  		base64EncodedStringSliceElement0 = base64.StdEncoding.EncodeToString([]byte(base64DecodedStringSliceElement0))
   343  		base64EncodedStringSliceElement1 = base64.StdEncoding.EncodeToString([]byte(base64DecodedStringSliceElement1))
   344  		confMap                          = MakeConfMap()
   345  		err                              error
   346  	)
   347  
   348  	err = confMap.UpdateFromString("TestNamespace:Test_-_Section.Test_-_OptionStringSlice1=")
   349  	if nil != err {
   350  		t.Fatalf("Couldn't add TestNamespace:Test_-_Section.Test_-_OptionStringSlice1=: %v", err)
   351  	}
   352  	err = confMap.UpdateFromString("TestNamespace:Test_-_Section.Test_-_OptionStringSlice2=TestString1,TestString2")
   353  	if nil != err {
   354  		t.Fatalf("Couldn't add TestNamespace:Test_-_Section.Test_-_OptionStringSlice2=TestString1,TestString2: %v", err)
   355  	}
   356  	err = confMap.UpdateFromString("TestNamespace:Test_-_Section.Test_-_OptionString=TestString3")
   357  	if nil != err {
   358  		t.Fatalf("Couldn't add TestNamespace:Test_-_Section.Test_-_OptionString=TestString3: %v", err)
   359  	}
   360  	err = confMap.UpdateFromString("TestNamespace:Test_-_Section.Test_-_OptionBase64String=" + base64EncodedString)
   361  	if nil != err {
   362  		t.Fatalf("Couldn't add TestNamespace:Test_-_Section.Test_-_OptionBase64String=" + base64EncodedString)
   363  	}
   364  	err = confMap.UpdateFromString("TestNamespace:Test_-_Section.Test_-_OptionBase64StringSlice=" + base64EncodedStringSliceElement0 + "," + base64EncodedStringSliceElement1)
   365  	if nil != err {
   366  		t.Fatalf("Couldn't add TestNamespace:Test_-_Section.Test_-_OptionBase64StringSlice=" + base64EncodedStringSliceElement0 + "," + base64EncodedStringSliceElement1)
   367  	}
   368  	err = confMap.UpdateFromString("TestNamespace:Test_-_Section.Test_-_OptionBool=true")
   369  	if nil != err {
   370  		t.Fatalf("Couldn't add TestNamespace:Test_-_Section.Test_-_OptionBool=true: %v", err)
   371  	}
   372  	err = confMap.UpdateFromString("TestNamespace:Test_-_Section.Test_-_OptionUint8=91")
   373  	if nil != err {
   374  		t.Fatalf("Couldn't add TestNamespace:Test_-_Section.Test_-_OptionUint8=91: %v", err)
   375  	}
   376  	err = confMap.UpdateFromString("TestNamespace:Test_-_Section.Test_-_OptionUint16=12")
   377  	if nil != err {
   378  		t.Fatalf("Couldn't add TestNamespace:Test_-_Section.Test_-_OptionUint16=12: %v", err)
   379  	}
   380  	err = confMap.UpdateFromString("TestNamespace:Test_-_Section.Test_-_OptionUint32=345")
   381  	if nil != err {
   382  		t.Fatalf("Couldn't add TestNamespace:Test_-_Section.Test_-_OptionUint32=345: %v", err)
   383  	}
   384  	err = confMap.UpdateFromString("TestNamespace:Test_-_Section.Test_-_OptionUint64=6789")
   385  	if nil != err {
   386  		t.Fatalf("Couldn't add TestNamespace:Test_-_Section.Test_-_OptionUint64=6789: %v", err)
   387  	}
   388  	err = confMap.UpdateFromString("TestNamespace:Test_-_Section.Test_-_OptionMilliseconds32=0.123")
   389  	if nil != err {
   390  		t.Fatalf("Couldn't add TestNamespace:Test_-_Section.Test_-_OptionMilliseconds32=0.123: %v", err)
   391  	}
   392  	err = confMap.UpdateFromString("TestNamespace:Test_-_Section.Test_-_OptionMilliseconds64=0.456")
   393  	if nil != err {
   394  		t.Fatalf("Couldn't add TestNamespace:Test_-_Section.Test_-_OptionMilliseconds64=0.456: %v", err)
   395  	}
   396  	err = confMap.UpdateFromString("TestNamespace:Test_-_Section.Test_-_OptionDuration=1.2s")
   397  	if nil != err {
   398  		t.Fatalf("Couldn't add TestNamespace:Test_-_Section.Test_-_OptionDuration=1.2s: %v", err)
   399  	}
   400  	err = confMap.UpdateFromString("TestNamespace:Test_-_Section.Test_-_OptionGUIDString=12345678-1234-1234-1234-123456789ABC")
   401  	if nil != err {
   402  		t.Fatalf("Couldn't add TestNamespace:Test_-_Section.Test_-_OptionGUIDString=12345678-1234-1234-1234-123456789ABC: %v", err)
   403  	}
   404  
   405  	err = confMap.VerifyOptionIsMissing("TestNamespace:Test_-_Section", "Test_-_OptionStringSlice0")
   406  	if nil != err {
   407  		t.Fatalf("TestNamespace:Test_-_Section.Test_-_OptionStringSlice0 should have verified as missing")
   408  	}
   409  	err = confMap.VerifyOptionIsMissing("TestNamespace:Test_-_Section", "Test_-_OptionStringSlice1")
   410  	if nil == err {
   411  		t.Fatalf("TestNamespace:Test_-_Section.Test_-_OptionStringSlice1 should have verified as not missing")
   412  	}
   413  
   414  	err = confMap.VerifyOptionValueIsEmpty("TestNamespace:Test_-_Section", "Test_-_OptionStringSlice1")
   415  	if nil != err {
   416  		t.Fatalf("TestNamespace:Test_-_Section.Test_-_OptionStringSlice1 should have verified as empty")
   417  	}
   418  	err = confMap.VerifyOptionValueIsEmpty("TestNamespace:Test_-_Section", "Test_-_OptionStringSlice2")
   419  	if nil == err {
   420  		t.Fatalf("TestNamespace:Test_-_Section.Test_-_OptionStringSlice2 should have verified as not empty")
   421  	}
   422  
   423  	testStringSlice1, err := confMap.FetchOptionValueStringSlice("TestNamespace:Test_-_Section", "Test_-_OptionStringSlice1")
   424  	if nil != err {
   425  		t.Fatalf("Couldn't fetch TestNamespace:Test_-_Section.Test_-_OptionStringSlice1: %v", err)
   426  	}
   427  	testStringSlice2, err := confMap.FetchOptionValueStringSlice("TestNamespace:Test_-_Section", "Test_-_OptionStringSlice2")
   428  	if nil != err {
   429  		t.Fatalf("Couldn't fetch TestNamespace:Test_-_Section.Test_-_OptionStringSlice2: %v", err)
   430  	}
   431  	testString, err := confMap.FetchOptionValueString("TestNamespace:Test_-_Section", "Test_-_OptionString")
   432  	if nil != err {
   433  		t.Fatalf("Couldn't fetch TestNamespace:Test_-_Section.Test_-_OptionString: %v", err)
   434  	}
   435  	testBase64String, err := confMap.FetchOptionValueBase64String("TestNamespace:Test_-_Section", "Test_-_OptionBase64String")
   436  	if nil != err {
   437  		t.Fatalf("Couldn't fetch TestNamespace:Test_-_Section.Test_-_OptionBase64String: %v", err)
   438  	}
   439  	testBase64StringSlice, err := confMap.FetchOptionValueBase64StringSlice("TestNamespace:Test_-_Section", "Test_-_OptionBase64StringSlice")
   440  	if nil != err {
   441  		t.Fatalf("Couldn't fetch TestNamespace:Test_-_Section.Test_-_OptionBase64StringSlice: %v", err)
   442  	}
   443  	testBool, err := confMap.FetchOptionValueBool("TestNamespace:Test_-_Section", "Test_-_OptionBool")
   444  	if err != nil {
   445  		t.Fatalf("Couldn't fetch TestNamespace:Test_-_Section.Test_-_OptionBool: %v", err)
   446  	}
   447  	testUint8, err := confMap.FetchOptionValueUint8("TestNamespace:Test_-_Section", "Test_-_OptionUint8")
   448  	if nil != err {
   449  		t.Fatalf("Couldn't fetch TestNamespace:Test_-_Section.Test_-_OptionUint8: %v", err)
   450  	}
   451  	testUint16, err := confMap.FetchOptionValueUint16("TestNamespace:Test_-_Section", "Test_-_OptionUint16")
   452  	if nil != err {
   453  		t.Fatalf("Couldn't fetch TestNamespace:Test_-_Section.Test_-_OptionUint16: %v", err)
   454  	}
   455  	testUint32, err := confMap.FetchOptionValueUint32("TestNamespace:Test_-_Section", "Test_-_OptionUint32")
   456  	if nil != err {
   457  		t.Fatalf("Couldn't fetch TestNamespace:Test_-_Section.Test_-_OptionUint32: %v", err)
   458  	}
   459  	testUint64, err := confMap.FetchOptionValueUint64("TestNamespace:Test_-_Section", "Test_-_OptionUint64")
   460  	if nil != err {
   461  		t.Fatalf("Couldn't fetch TestNamespace:Test_-_Section.Test_-_OptionUint64: %v", err)
   462  	}
   463  	testFloat32, err := confMap.FetchOptionValueFloat32("TestNamespace:Test_-_Section", "Test_-_OptionMilliseconds32")
   464  	if nil != err {
   465  		t.Fatalf("Couldn't fetch TestNamespace:Test_-_Section.Test_-_OptionMilliseconds32 as float32: %v", err)
   466  	}
   467  	testFloat64, err := confMap.FetchOptionValueFloat64("TestNamespace:Test_-_Section", "Test_-_OptionMilliseconds64")
   468  	if nil != err {
   469  		t.Fatalf("Couldn't fetch TestNamespace:Test_-_Section.Test_-_OptionMilliseconds64 as float64: %v", err)
   470  	}
   471  	testScaledUint32, err := confMap.FetchOptionValueFloatScaledToUint32("TestNamespace:Test_-_Section", "Test_-_OptionMilliseconds32", 1000)
   472  	if nil != err {
   473  		t.Fatalf("Couldn't fetch TestNamespace:Test_-_Section.Test_-_OptionMilliseconds32 as uint32: %v", err)
   474  	}
   475  	testScaledUint64, err := confMap.FetchOptionValueFloatScaledToUint64("TestNamespace:Test_-_Section", "Test_-_OptionMilliseconds64", 1000)
   476  	if nil != err {
   477  		t.Fatalf("Couldn't fetch TestNamespace:Test_-_Section.Test_-_OptionMilliseconds64 as uint64: %v", err)
   478  	}
   479  	testDuration, err := confMap.FetchOptionValueDuration("TestNamespace:Test_-_Section", "Test_-_OptionDuration")
   480  	if nil != err {
   481  		t.Fatalf("Couldn't fetch TestNamespace:Test_-_Section.TestDuration: %v", err)
   482  	}
   483  	testGUID, err := confMap.FetchOptionValueUUID("TestNamespace:Test_-_Section", "Test_-_OptionGUIDString")
   484  	if nil != err {
   485  		t.Fatalf("Couldn't fetch TestNamespace:Test_-_Section.Test_-_OptionGUIDString: %v", err)
   486  	}
   487  
   488  	if 0 != len(testStringSlice1) {
   489  		t.Fatalf("TestNamespace:Test_-_Section.Test_-_OptionStringSlice1 contained unexpected value(s)")
   490  	}
   491  	if (2 != len(testStringSlice2)) || ("TestString1" != testStringSlice2[0]) || ("TestString2" != testStringSlice2[1]) {
   492  		t.Fatalf("TestNamespace:Test_-_Section.Test_-_OptionStringSlice2 contained unexpected value(s)")
   493  	}
   494  	if "TestString3" != testString {
   495  		t.Fatalf("TestNamespace:Test_-_Section.Test_-_OptionString contained unexpected value")
   496  	}
   497  	if base64DecodedString != testBase64String {
   498  		t.Fatalf("TestNamespace:Test_-_Section.Test_-_OptionBase64String contained unexpected value")
   499  	}
   500  	if (2 != len(testBase64StringSlice)) || (base64DecodedStringSliceElement0 != base64DecodedStringSliceElement0) || (base64DecodedStringSliceElement1 != base64DecodedStringSliceElement1) {
   501  		t.Fatalf("TestNamespace:Test_-_Section.Test_-_OptionBase64StringSlice contained unexpected value(s)")
   502  	}
   503  	if testBool != true {
   504  		t.Fatalf("TestNamespace:Test_-_Section.TestBool contained unexpected value")
   505  	}
   506  	if uint8(91) != testUint8 {
   507  		t.Fatalf("TestNamespace:Test_-_Section.Test_-_OptionUint8 contained unexpected value")
   508  	}
   509  	if uint16(12) != testUint16 {
   510  		t.Fatalf("TestNamespace:Test_-_Section.Test_-_OptionUint16 contained unexpected value")
   511  	}
   512  	if uint32(345) != testUint32 {
   513  		t.Fatalf("TestNamespace:Test_-_Section.Test_-_OptionUint32 contained unexpected value")
   514  	}
   515  	if uint64(6789) != testUint64 {
   516  		t.Fatalf("TestNamespace:Test_-_Section.Test_-_OptionUint64 contained unexpected value")
   517  	}
   518  	if float32(0.123) != testFloat32 {
   519  		t.Fatalf("TestNamespace:Test_-_Section.Test_-_OptionMilliseconds32 contained unexpected float32 value")
   520  	}
   521  	if float64(0.456) != testFloat64 {
   522  		t.Fatalf("TestNamespace:Test_-_Section.Test_-_OptionMilliseconds64 contained unexpected float64 value")
   523  	}
   524  	if uint32(123) != testScaledUint32 {
   525  		t.Fatalf("TestNamespace:Test_-_Section.Test_-_OptionMilliseconds32 contained unexpected uint32 value")
   526  	}
   527  	if uint64(456) != testScaledUint64 {
   528  		t.Fatalf("TestNamespace:Test_-_Section.Test_-_OptionMilliseconds64 contained unexpected uint64 value")
   529  	}
   530  	timeBase := time.Time{}
   531  	timeBasePlusTestDuration := timeBase.Add(testDuration)
   532  	if (1 != timeBasePlusTestDuration.Second()) || (200000000 != timeBasePlusTestDuration.Nanosecond()) {
   533  		t.Fatalf("TestNamespace:Test_-_Section.TestDuration contained unexpected value")
   534  	}
   535  	if 0 != bytes.Compare([]byte{0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}, testGUID) {
   536  		t.Fatalf("TestNamespace:Test_-_Section.Test_-_OptionGUIDString contained unexpected value")
   537  	}
   538  }
   539  
   540  func TestInclude(t *testing.T) {
   541  	_, err := MakeConfMapFromFile(tempFile5Name)
   542  	if nil != err {
   543  		t.Fatalf("MakeConfMapFromFile() of <tempdir>/%v that includes <tempdir>/%v got %#v", filepath.Base(tempFile5Name), filepath.Base(tempFile4Name), err)
   544  	}
   545  }
   546  
   547  func TestDump(t *testing.T) {
   548  	var (
   549  		confMap6 = MakeConfMap()
   550  		confMap7 = MakeConfMap()
   551  	)
   552  
   553  	err := confMap6.UpdateFromFile(tempFile6Name)
   554  	if nil != err {
   555  		t.Fatalf("UpdateConfMapFromFile(\"%v\") returned: \"%v\"", tempFile6Name, err)
   556  	}
   557  
   558  	err = confMap6.DumpConfMapToFile(tempFile7Name, os.FileMode(0600))
   559  	if nil != err {
   560  		t.Fatalf("DumpConfMapToFile() returned: \"%v\"", err)
   561  	}
   562  
   563  	err = confMap7.UpdateFromFile(tempFile7Name)
   564  	if nil != err {
   565  		t.Fatalf("UpdateConfMapFromFile(\"%v\") returned: \"%v\"", tempFile7Name, err)
   566  	}
   567  
   568  	if !reflect.DeepEqual(confMap6, confMap7) {
   569  		t.Fatalf("DumpConfMapToFile() failed to reproduce \"%v\" into \"%v\"", tempFile6Name, tempFile7Name)
   570  	}
   571  }
   572  
   573  // test SetOptionIfMissing and SetSectionIfMissing
   574  func TestIfMissing(t *testing.T) {
   575  
   576  	assert := assert.New(t)
   577  
   578  	// create an empty confMap and populate it with one option (in one section)
   579  	confMap := MakeConfMap()
   580  
   581  	testSectionName0 := "TestSection0"
   582  	testSectionName1 := "TestSection1e"
   583  	testOptionName0 := "Test_-_Option0"
   584  	testOptionName1 := "Test_-_Option1"
   585  	testOptionString0 := "OptionValue0"
   586  	missingOptionString0 := "DefaultString0"
   587  	missingOptionString1 := "DefaultString1"
   588  
   589  	confStringToSection0Option0 := testSectionName0 + "." + testOptionName0 + " = " + testOptionString0
   590  
   591  	// populate testSectionName0.testOptionName0
   592  	err := confMap.UpdateFromString(confStringToSection0Option0)
   593  	assert.NoError(err, "UpdateFromString() should not fail with a valid option string")
   594  
   595  	// verify option was set
   596  	optionString, err := confMap.FetchOptionValueString(testSectionName0, testOptionName0)
   597  	assert.NoError(err, "FetchOptionValueString() cannot fail a valid request")
   598  	assert.Equal(testOptionString0, optionString, "FetchOptionValueString should return the option that was set")
   599  
   600  	missingOptionValue0 := ConfMapOption{missingOptionString0}
   601  	missingOptionValue1 := ConfMapOption{missingOptionString1}
   602  
   603  	// a new ConfMapOption should not overwrite the existing one
   604  	confMap.SetOptionIfMissing(testSectionName0, testOptionName0, missingOptionValue0)
   605  
   606  	optionString, err = confMap.FetchOptionValueString(testSectionName0, testOptionName0)
   607  	assert.NoError(err, "FetchOptionalValueString should not fail since the option exists")
   608  	assert.Equal(testOptionString0, optionString, "SetOptionIfMissing should not change existing optionValue")
   609  
   610  	// but a new ConfMapOption should replace a missing one
   611  	optionString, err = confMap.FetchOptionValueString(testSectionName0, testOptionName1)
   612  	assert.Error(err, "FetchOptionalValueString should fail since '%s' has not been set", testOptionName1)
   613  
   614  	confMap.SetOptionIfMissing(testSectionName0, testOptionName1, missingOptionValue1)
   615  
   616  	optionString, err = confMap.FetchOptionValueString(testSectionName0, testOptionName1)
   617  	assert.NoError(err, "FetchOptionalValueString should not fail since missing value was set")
   618  	assert.Equal(missingOptionString1, optionString, "SetOptionIfMissing should have set missing value")
   619  
   620  	// repeat a similar set of tests for sections
   621  	//
   622  	// verify option still exists
   623  	optionString, err = confMap.FetchOptionValueString(testSectionName0, testOptionName0)
   624  	assert.NoError(err, "FetchOptionValueString() cannot fail a valid request")
   625  
   626  	// a new ConfMapSection should not overwrite an existing one
   627  	missingSection0 := ConfMapSection{
   628  		testOptionName0: ConfMapOption{missingOptionString0},
   629  		testOptionName1: ConfMapOption{missingOptionString1},
   630  	}
   631  	confMap.SetSectionIfMissing(testSectionName0, missingSection0)
   632  
   633  	optionString, err = confMap.FetchOptionValueString(testSectionName0, testOptionName0)
   634  	assert.NoError(err, "FetchOptionalValueString should not fail since the option exists")
   635  	assert.Equal(testOptionString0, optionString, "SetOptionIfMissing should not change existing optionValue")
   636  
   637  	optionString, err = confMap.FetchOptionValueString(testSectionName0, testOptionName1)
   638  	assert.NoError(err, "second option should have been added")
   639  	assert.Equal(missingOptionString1, optionString, "SetOptionIfMissing should not change existing optionValue")
   640  
   641  	// but a new ConfMapSection should replace a missing one
   642  	confMap.SetSectionIfMissing(testSectionName1, missingSection0)
   643  
   644  	optionString, err = confMap.FetchOptionValueString(testSectionName1, testOptionName0)
   645  	assert.NoError(err, "FetchOptionalValueString should not fail since section was added")
   646  	assert.Equal(missingOptionString0, optionString, "missing Option should have been set")
   647  
   648  	optionString, err = confMap.FetchOptionValueString(testSectionName1, testOptionName1)
   649  	assert.NoError(err, "FetchOptionalValueString should not fail since section was added")
   650  	assert.Equal(missingOptionString1, optionString, "missing Option should have been set")
   651  }