1// Copyright (c) 2017, OpenPeeDeeP. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package xdg 6 7import ( 8 "fmt" 9 "os" 10 "path/filepath" 11 "strings" 12 "testing" 13 14 "github.com/stretchr/testify/assert" 15 "github.com/stretchr/testify/mock" 16) 17 18type mockDefaulter struct { 19 mock.Mock 20} 21 22func (m *mockDefaulter) defaultDataHome() string { 23 args := m.Called() 24 return args.String(0) 25} 26func (m *mockDefaulter) defaultDataDirs() []string { 27 args := m.Called() 28 return args.Get(0).([]string) 29} 30func (m *mockDefaulter) defaultConfigHome() string { 31 args := m.Called() 32 return args.String(0) 33} 34func (m *mockDefaulter) defaultConfigDirs() []string { 35 args := m.Called() 36 return args.Get(0).([]string) 37} 38func (m *mockDefaulter) defaultCacheHome() string { 39 args := m.Called() 40 return args.String(0) 41} 42 43const ( 44 MDataHome = iota 45 MDataDirs 46 MConfigHome 47 MConfigDirs 48 MCacheHome 49) 50 51var getterTestCases = []getterTestCase{ 52 {"DataHome Without", "defaultDataHome", filepath.Clean("/some/path"), true, "XDG_DATA_HOME", "", MDataHome, nil, filepath.Clean("/some/path")}, 53 {"DataDirs Without", "defaultDataDirs", []string{filepath.Clean("/some/path"), filepath.Clean("/some/other/path")}, true, "XDG_DATA_DIRS", "", MDataDirs, nil, []string{filepath.Clean("/some/path"), filepath.Clean("/some/other/path")}}, 54 {"ConfigHome Without", "defaultConfigHome", filepath.Clean("/some/path"), true, "XDG_CONFIG_HOME", "", MConfigHome, nil, filepath.Clean("/some/path")}, 55 {"ConfigDirs Without", "defaultConfigDirs", []string{filepath.Clean("/some/path"), filepath.Clean("/some/other/path")}, true, "XDG_CONFIG_DIRS", "", MConfigDirs, nil, []string{filepath.Clean("/some/path"), filepath.Clean("/some/other/path")}}, 56 {"CacheHome Without", "defaultCacheHome", filepath.Clean("/some/path"), true, "XDG_CACHE_HOME", "", MCacheHome, nil, filepath.Clean("/some/path")}, 57 58 {"DataHome With", "defaultDataHome", filepath.Clean("/wrong/path"), false, "XDG_DATA_HOME", filepath.Clean("/some/path"), MDataHome, nil, filepath.Clean("/some/path")}, 59 {"DataDirs With", "defaultDataDirs", []string{filepath.Clean("/wrong/path"), filepath.Clean("/some/other/wrong")}, false, "XDG_DATA_DIRS", strings.Join([]string{filepath.Clean("/some/path"), filepath.Clean("/some/other/path")}, string(os.PathListSeparator)), MDataDirs, nil, []string{filepath.Clean("/some/path"), filepath.Clean("/some/other/path")}}, 60 {"ConfigHome With", "defaultConfigHome", filepath.Clean("/wrong/path"), false, "XDG_CONFIG_HOME", filepath.Clean("/some/path"), MConfigHome, nil, filepath.Clean("/some/path")}, 61 {"ConfigDirs With", "defaultConfigDirs", []string{filepath.Clean("/wrong/path"), filepath.Clean("/some/other/wrong")}, false, "XDG_CONFIG_DIRS", strings.Join([]string{filepath.Clean("/some/path"), filepath.Clean("/some/other/path")}, string(os.PathListSeparator)), MConfigDirs, nil, []string{filepath.Clean("/some/path"), filepath.Clean("/some/other/path")}}, 62 {"CacheHome With", "defaultCacheHome", filepath.Clean("/wrong/path"), false, "XDG_CACHE_HOME", filepath.Clean("/some/path"), MCacheHome, nil, filepath.Clean("/some/path")}, 63 64 {"DataHome App Without", "defaultDataHome", filepath.Clean("/some/path"), true, "XDG_DATA_HOME", "", MDataHome, New("OpenPeeDeeP", "XDG"), filepath.Clean("/some/path/OpenPeeDeeP/XDG")}, 65 {"DataDirs App Without", "defaultDataDirs", []string{filepath.Clean("/some/path"), filepath.Clean("/some/other/path")}, true, "XDG_DATA_DIRS", "", MDataDirs, New("OpenPeeDeeP", "XDG"), []string{filepath.Clean("/some/path/OpenPeeDeeP/XDG"), filepath.Clean("/some/other/path/OpenPeeDeeP/XDG")}}, 66 {"ConfigHome App Without", "defaultConfigHome", filepath.Clean("/some/path"), true, "XDG_CONFIG_HOME", "", MConfigHome, New("OpenPeeDeeP", "XDG"), filepath.Clean("/some/path/OpenPeeDeeP/XDG")}, 67 {"ConfigDirs App Without", "defaultConfigDirs", []string{filepath.Clean("/some/path"), filepath.Clean("/some/other/path")}, true, "XDG_CONFIG_DIRS", "", MConfigDirs, New("OpenPeeDeeP", "XDG"), []string{filepath.Clean("/some/path/OpenPeeDeeP/XDG"), filepath.Clean("/some/other/path/OpenPeeDeeP/XDG")}}, 68 {"CacheHome App Without", "defaultCacheHome", filepath.Clean("/some/path"), true, "XDG_CACHE_HOME", "", MCacheHome, New("OpenPeeDeeP", "XDG"), filepath.Clean("/some/path/OpenPeeDeeP/XDG")}, 69 70 {"DataHome App With", "defaultDataHome", filepath.Clean("/wrong/path"), false, "XDG_DATA_HOME", filepath.Clean("/some/path"), MDataHome, New("OpenPeeDeeP", "XDG"), filepath.Clean("/some/path/OpenPeeDeeP/XDG")}, 71 {"DataDirs App With", "defaultDataDirs", []string{filepath.Clean("/wrong/path"), filepath.Clean("/some/other/wrong")}, false, "XDG_DATA_DIRS", strings.Join([]string{filepath.Clean("/some/path"), filepath.Clean("/some/other/path")}, string(os.PathListSeparator)), MDataDirs, New("OpenPeeDeeP", "XDG"), []string{filepath.Clean("/some/path/OpenPeeDeeP/XDG"), filepath.Clean("/some/other/path/OpenPeeDeeP/XDG")}}, 72 {"ConfigHome App With", "defaultConfigHome", filepath.Clean("/wrong/path"), false, "XDG_CONFIG_HOME", filepath.Clean("/some/path"), MConfigHome, New("OpenPeeDeeP", "XDG"), filepath.Clean("/some/path/OpenPeeDeeP/XDG")}, 73 {"ConfigDirs App With", "defaultConfigDirs", []string{filepath.Clean("/wrong/path"), filepath.Clean("/some/other/wrong")}, false, "XDG_CONFIG_DIRS", strings.Join([]string{filepath.Clean("/some/path"), filepath.Clean("/some/other/path")}, string(os.PathListSeparator)), MConfigDirs, New("OpenPeeDeeP", "XDG"), []string{filepath.Clean("/some/path/OpenPeeDeeP/XDG"), filepath.Clean("/some/other/path/OpenPeeDeeP/XDG")}}, 74 {"CacheHome App With", "defaultCacheHome", filepath.Clean("/wrong/path"), false, "XDG_CACHE_HOME", filepath.Clean("/some/path"), MCacheHome, New("OpenPeeDeeP", "XDG"), filepath.Clean("/some/path/OpenPeeDeeP/XDG")}, 75} 76 77type getterTestCase struct { 78 name string 79 mokedMethod string 80 mockedReturn interface{} 81 calledMocked bool 82 env string 83 envVal string 84 method int 85 xdgApp *XDG 86 expected interface{} 87} 88 89func TestXDG_Getters(t *testing.T) { 90 for _, tc := range getterTestCases { 91 t.Run(tc.name, func(t *testing.T) { 92 assert := assert.New(t) 93 mockDef := new(mockDefaulter) 94 mockDef.On(tc.mokedMethod).Return(tc.mockedReturn) 95 setDefaulter(mockDef) 96 os.Setenv(tc.env, tc.envVal) // nolint: errcheck 97 98 actual := computeActual(tc) 99 100 if tc.calledMocked { 101 mockDef.AssertExpectations(t) 102 } else { 103 mockDef.AssertNotCalled(t, tc.mokedMethod) 104 } 105 assert.Equal(tc.expected, actual) 106 }) 107 } 108} 109 110// nolint: gocyclo 111func computeActual(tc getterTestCase) interface{} { 112 var actual interface{} 113 switch tc.method { 114 case MDataHome: 115 if tc.xdgApp != nil { 116 actual = tc.xdgApp.DataHome() 117 } else { 118 actual = DataHome() 119 } 120 case MDataDirs: 121 if tc.xdgApp != nil { 122 actual = tc.xdgApp.DataDirs() 123 } else { 124 actual = DataDirs() 125 } 126 case MConfigHome: 127 if tc.xdgApp != nil { 128 actual = tc.xdgApp.ConfigHome() 129 } else { 130 actual = ConfigHome() 131 } 132 case MConfigDirs: 133 if tc.xdgApp != nil { 134 actual = tc.xdgApp.ConfigDirs() 135 } else { 136 actual = ConfigDirs() 137 } 138 case MCacheHome: 139 if tc.xdgApp != nil { 140 actual = tc.xdgApp.CacheHome() 141 } else { 142 actual = CacheHome() 143 } 144 } 145 return actual 146} 147 148const ( 149 QData = iota 150 QConfig 151 QCache 152) 153 154var ( 155 root = "testingFolder" 156 fileTypes = []string{"data", "config", "cache"} 157 fileLoc = []string{"home", "dirs"} 158) 159 160type queryTestCase struct { 161 name string 162 xdgApp *XDG 163 queryType int 164 filename string 165 expected string 166} 167 168var queryTestCases = []queryTestCase{ 169 {"Data Dirs", New("OpenPeeDeeP", "XDG"), QData, "XDG_DATA_DIRS.txt", filepath.Clean("/data/dirs/OpenPeeDeeP/XDG/XDG_DATA_DIRS.txt")}, 170 {"Data Home", New("OpenPeeDeeP", "XDG"), QData, "XDG_DATA_HOME.txt", filepath.Clean("/data/home/OpenPeeDeeP/XDG/XDG_DATA_HOME.txt")}, 171 {"Data DNE", New("OpenPeeDeeP", "XDG"), QData, "XDG_CONFIG_HOME.txt", ""}, 172 173 {"Config Dirs", New("OpenPeeDeeP", "XDG"), QConfig, "XDG_CONFIG_DIRS.txt", filepath.Clean("/config/dirs/OpenPeeDeeP/XDG/XDG_CONFIG_DIRS.txt")}, 174 {"Config Home", New("OpenPeeDeeP", "XDG"), QConfig, "XDG_CONFIG_HOME.txt", filepath.Clean("/config/home/OpenPeeDeeP/XDG/XDG_CONFIG_HOME.txt")}, 175 {"Config DNE", New("OpenPeeDeeP", "XDG"), QConfig, "XDG_DATA_HOME.txt", ""}, 176 177 {"Cache Home", New("OpenPeeDeeP", "XDG"), QCache, "XDG_CACHE_HOME.txt", filepath.Clean("/cache/home/OpenPeeDeeP/XDG/XDG_CACHE_HOME.txt")}, 178 {"Cache DNE", New("OpenPeeDeeP", "XDG"), QCache, "XDG_CACHE_DIRS.txt", ""}, 179} 180 181func TestXDG_Query(t *testing.T) { 182 for _, tc := range queryTestCases { 183 t.Run(tc.name, func(t *testing.T) { 184 defer teardownQueryData() //nolint: errcheck 185 standupQueryData(tc) //nolint: errcheck 186 assert := assert.New(t) 187 actual := computeQuery(tc) 188 assert.Equal(tc.expected, actual) 189 }) 190 } 191} 192 193func computeQuery(tc queryTestCase) string { 194 var actual string 195 switch tc.queryType { 196 case QData: 197 actual = tc.xdgApp.QueryData(tc.filename) 198 case QCache: 199 actual = tc.xdgApp.QueryCache(tc.filename) 200 case QConfig: 201 actual = tc.xdgApp.QueryConfig(tc.filename) 202 } 203 rootAbs, _ := filepath.Abs(root) 204 actual = strings.Replace(actual, rootAbs, "", 1) 205 return actual 206} 207 208func standupQueryData(tc queryTestCase) error { 209 for _, t := range fileTypes { 210 for _, l := range fileLoc { 211 path, err := filepath.Abs(filepath.Join(root, t, l)) 212 if err != nil { 213 return err 214 } 215 if err = os.MkdirAll(filepath.Join(path, tc.xdgApp.Vendor, tc.xdgApp.Application), 0777); err != nil { 216 return err 217 } 218 envVar := fmt.Sprintf("XDG_%s_%s", strings.ToUpper(t), strings.ToUpper(l)) 219 if err = os.Setenv(envVar, path); err != nil { 220 return err 221 } 222 file, err := os.OpenFile(filepath.Join(path, tc.xdgApp.Vendor, tc.xdgApp.Application, envVar+".txt"), os.O_CREATE|os.O_RDONLY, 0666) 223 if err != nil { 224 return err 225 } 226 defer file.Close() //nolint: errcheck 227 } 228 } 229 return nil 230} 231 232func teardownQueryData() error { 233 return os.RemoveAll(root) 234} 235