github.com/JBoudou/Itero@v0.1.7/pkg/config/config_test.go (about)

     1  // Itero - Online iterative vote application
     2  // Copyright (C) 2020 Joseph Boudou
     3  //
     4  // This program is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Affero General Public License as
     6  // published by the Free Software Foundation, either version 3 of the
     7  // License, or (at your option) any later version.
     8  //
     9  // This program is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  // GNU Affero General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Affero General Public License
    15  // along with this program.  If not, see <https://www.gnu.org/licenses/>.
    16  
    17  package config
    18  
    19  import (
    20  	"bytes"
    21  	"errors"
    22  	"fmt"
    23  	"os"
    24  	"path/filepath"
    25  	"testing"
    26  )
    27  
    28  type myCompoundStruct struct {
    29  	IntValue    int
    30  	StringValue string
    31  	FloatValue  float64
    32  	Z           string `json:"other"`
    33  	Array       [4]int
    34  }
    35  
    36  func TestValue(t *testing.T) {
    37  	ReadFile(t, "config.json", 2)
    38  
    39  	const key = "object"
    40  	var expected = myCompoundStruct{42, "foo", 3.14, "bar", [4]int{2, 3, 5, 8}}
    41  
    42  	const keyOther = "object.other"
    43  	var other = myCompoundStruct{27, "flu", 2.14, "blu", [4]int{1, 3, 13, 75}}
    44  
    45  	const keyPartial = "object.partial"
    46  	var partial = myCompoundStruct{26, "foo", 3.14, "blu", [4]int{2, 3, 5, 8}}
    47  
    48  	t.Run("found", func(t *testing.T) {
    49  		var got myCompoundStruct
    50  		err := Value(key, &got)
    51  
    52  		if err != nil {
    53  			t.Fatalf("Error: %v", err)
    54  		}
    55  		if got != expected {
    56  			t.Errorf("Got: %v. Expect: %v", got, expected)
    57  		}
    58  	})
    59  
    60  	t.Run("not found", func(t *testing.T) {
    61  		var got myCompoundStruct
    62  		err := Value(keyOther, &got)
    63  
    64  		if err == nil {
    65  			t.Fatalf("Key %s found", keyOther)
    66  		}
    67  		knf, ok := err.(KeyNotFound)
    68  		if !ok {
    69  			t.Fatalf("Wrong type for error")
    70  		}
    71  		if string(knf) != keyOther {
    72  			t.Fatalf("Wrong key not found. Got: %s. Expect: %s.", string(knf), keyOther)
    73  		}
    74  	})
    75  
    76  	t.Run("or found", func(t *testing.T) {
    77  		var got myCompoundStruct
    78  		err := ValueOr(key, &got, &other)
    79  
    80  		if err != nil {
    81  			t.Fatalf("Error: %v", err)
    82  		}
    83  		if got != expected {
    84  			t.Errorf("Got: %v. Expect: %v", got, expected)
    85  		}
    86  	})
    87  
    88  	t.Run("or not found", func(t *testing.T) {
    89  		var got myCompoundStruct
    90  		err := Value(keyOther, &got)
    91  		if err == nil {
    92  			t.Fatalf("Key %s found", keyOther)
    93  		}
    94  
    95  		err = ValueOr(keyOther, &got, &expected)
    96  
    97  		if err != nil {
    98  			t.Fatalf("Error: %v", err)
    99  		}
   100  		if got != expected {
   101  			t.Errorf("Got: %v. Expect: %v", got, expected)
   102  		}
   103  		err = Value(keyOther, &got)
   104  		if err != nil {
   105  			t.Fatalf("Error: %v", err)
   106  		}
   107  		if got != expected {
   108  			t.Errorf("Got: %v. Expect: %v", got, expected)
   109  		}
   110  	})
   111  
   112  	t.Run("partial", func(t *testing.T) {
   113  		got := partial
   114  		err := Value(keyPartial, &got)
   115  
   116  		if err != nil {
   117  			t.Fatalf("Error: %v", err)
   118  		}
   119  		if got == partial {
   120  			t.Errorf("Unchanged")
   121  		}
   122  		if got != expected {
   123  			t.Errorf("Got: %v. Expect: %v", got, expected)
   124  		}
   125  	})
   126  }
   127  
   128  func TestFindFileInParent(t *testing.T) {
   129  	tests := []struct {
   130  		name   string
   131  		pwd    string // from testdata
   132  		file   string
   133  		depth  int
   134  		expect string // from testdata
   135  		err    error
   136  	}{
   137  		{
   138  			name:  "Not found",
   139  			pwd:   "a/b/c/d",
   140  			file:  "notfound.txt",
   141  			depth: 3,
   142  			err:   os.ErrNotExist,
   143  		},
   144  		{
   145  			name:   "Direct",
   146  			pwd:    "a/b/c/d",
   147  			file:   "foo.txt",
   148  			depth:  3,
   149  			expect: "a/b/c/d",
   150  		},
   151  		{
   152  			name:   "Last",
   153  			pwd:    "a/b/c/d",
   154  			file:   "foo.cfg",
   155  			depth:  3,
   156  			expect: "a",
   157  		},
   158  		{
   159  			name:  "Too deep",
   160  			pwd:   "a/b/c/d",
   161  			file:  "foo.ini",
   162  			depth: 3,
   163  			err:   os.ErrNotExist,
   164  		},
   165  	}
   166  
   167  	for _, tt := range tests {
   168  		// Not parallel because CWD is per thread and thread != goroutines.
   169  		t.Run(tt.name, func(t *testing.T) {
   170  			tt.pwd = filepath.FromSlash(tt.pwd)
   171  			tt.expect = filepath.FromSlash(tt.expect)
   172  
   173  			expectabs, _ := filepath.Abs(filepath.Join("testdata", tt.expect))
   174  			origin, _ := os.Getwd()
   175  			os.Chdir(filepath.Join("testdata", tt.pwd))
   176  			defer os.Chdir(origin)
   177  
   178  			got, err := FindFileInParent(tt.file, tt.depth)
   179  
   180  			if tt.err == nil {
   181  				if err != nil {
   182  					t.Errorf("Got unexpected error %v.", err)
   183  				} else {
   184  					if got != tt.expect {
   185  						gotabs, _ := filepath.Abs(got)
   186  						if gotabs != expectabs {
   187  							gotstat, _ := os.Stat(gotabs)
   188  							expectstat, _ := os.Stat(expectabs)
   189  							if !os.SameFile(gotstat, expectstat) {
   190  								t.Errorf("Wrong result. Got %s. Expect %s.", got, tt.expect)
   191  								t.Errorf("expectabs %s.", expectabs)
   192  							}
   193  						}
   194  					}
   195  				}
   196  			} else {
   197  				if !errors.Is(err, tt.err) {
   198  					t.Errorf("Wrong error. Got %v. Expect %v.", err, tt.err)
   199  				}
   200  			}
   201  		})
   202  	}
   203  }
   204  
   205  // Example //
   206  
   207  func Example() {
   208  	configMap := bytes.NewBufferString(`{
   209  		"Foo": 42,
   210  		"Bar": {"Baz": 1}
   211  	}`)
   212  	var foo int
   213  	var bar struct{ Baz int }
   214  
   215  	Read(configMap)
   216  	Value("Foo", &foo)
   217  	Value("Bar", &bar)
   218  
   219  	fmt.Println(foo, bar.Baz)
   220  	// Output:
   221  	// 42 1
   222  }