github.com/pietrocarrara/hugo@v0.47.1/hugolib/filesystems/basefs_test.go (about) 1 // Copyright 2018 The Hugo Authors. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package filesystems 15 16 import ( 17 "errors" 18 "fmt" 19 "os" 20 "path/filepath" 21 "testing" 22 23 "github.com/gohugoio/hugo/langs" 24 25 "github.com/spf13/afero" 26 27 "github.com/gohugoio/hugo/hugofs" 28 "github.com/gohugoio/hugo/hugolib/paths" 29 "github.com/spf13/viper" 30 "github.com/stretchr/testify/require" 31 ) 32 33 func TestNewBaseFs(t *testing.T) { 34 assert := require.New(t) 35 v := viper.New() 36 37 fs := hugofs.NewMem(v) 38 39 themes := []string{"btheme", "atheme"} 40 41 workingDir := filepath.FromSlash("/my/work") 42 v.Set("workingDir", workingDir) 43 v.Set("themesDir", "themes") 44 v.Set("theme", themes[:1]) 45 46 // Write some data to the themes 47 for _, theme := range themes { 48 for _, dir := range []string{"i18n", "data"} { 49 base := filepath.Join(workingDir, "themes", theme, dir) 50 fs.Source.Mkdir(base, 0755) 51 afero.WriteFile(fs.Source, filepath.Join(base, fmt.Sprintf("theme-file-%s-%s.txt", theme, dir)), []byte(fmt.Sprintf("content:%s:%s", theme, dir)), 0755) 52 } 53 // Write some files to the root of the theme 54 base := filepath.Join(workingDir, "themes", theme) 55 afero.WriteFile(fs.Source, filepath.Join(base, fmt.Sprintf("theme-root-%s.txt", theme)), []byte(fmt.Sprintf("content:%s", theme)), 0755) 56 afero.WriteFile(fs.Source, filepath.Join(base, "file-root.txt"), []byte(fmt.Sprintf("content:%s", theme)), 0755) 57 } 58 59 afero.WriteFile(fs.Source, filepath.Join(workingDir, "file-root.txt"), []byte("content-project"), 0755) 60 61 afero.WriteFile(fs.Source, filepath.Join(workingDir, "themes", "btheme", "config.toml"), []byte(` 62 theme = ["atheme"] 63 `), 0755) 64 65 setConfigAndWriteSomeFilesTo(fs.Source, v, "contentDir", "mycontent", 3) 66 setConfigAndWriteSomeFilesTo(fs.Source, v, "i18nDir", "myi18n", 4) 67 setConfigAndWriteSomeFilesTo(fs.Source, v, "layoutDir", "mylayouts", 5) 68 setConfigAndWriteSomeFilesTo(fs.Source, v, "staticDir", "mystatic", 6) 69 setConfigAndWriteSomeFilesTo(fs.Source, v, "dataDir", "mydata", 7) 70 setConfigAndWriteSomeFilesTo(fs.Source, v, "archetypeDir", "myarchetypes", 8) 71 setConfigAndWriteSomeFilesTo(fs.Source, v, "assetDir", "myassets", 9) 72 setConfigAndWriteSomeFilesTo(fs.Source, v, "resourceDir", "myrsesource", 10) 73 74 v.Set("publishDir", "public") 75 76 p, err := paths.New(fs, v) 77 assert.NoError(err) 78 79 bfs, err := NewBase(p) 80 assert.NoError(err) 81 assert.NotNil(bfs) 82 83 root, err := bfs.I18n.Fs.Open("") 84 assert.NoError(err) 85 dirnames, err := root.Readdirnames(-1) 86 assert.NoError(err) 87 assert.Equal([]string{projectVirtualFolder, "btheme", "atheme"}, dirnames) 88 ff, err := bfs.I18n.Fs.Open("myi18n") 89 assert.NoError(err) 90 _, err = ff.Readdirnames(-1) 91 assert.NoError(err) 92 93 root, err = bfs.Data.Fs.Open("") 94 assert.NoError(err) 95 dirnames, err = root.Readdirnames(-1) 96 assert.NoError(err) 97 assert.Equal([]string{projectVirtualFolder, "btheme", "atheme"}, dirnames) 98 ff, err = bfs.I18n.Fs.Open("mydata") 99 assert.NoError(err) 100 _, err = ff.Readdirnames(-1) 101 assert.NoError(err) 102 103 checkFileCount(bfs.Content.Fs, "", assert, 3) 104 checkFileCount(bfs.I18n.Fs, "", assert, 6) // 4 + 2 themes 105 checkFileCount(bfs.Layouts.Fs, "", assert, 5) 106 checkFileCount(bfs.Static[""].Fs, "", assert, 6) 107 checkFileCount(bfs.Data.Fs, "", assert, 9) // 7 + 2 themes 108 checkFileCount(bfs.Archetypes.Fs, "", assert, 8) 109 checkFileCount(bfs.Assets.Fs, "", assert, 9) 110 checkFileCount(bfs.Resources.Fs, "", assert, 10) 111 checkFileCount(bfs.Work.Fs, "", assert, 69) 112 113 assert.Equal([]string{filepath.FromSlash("/my/work/mydata"), filepath.FromSlash("/my/work/themes/btheme/data"), filepath.FromSlash("/my/work/themes/atheme/data")}, bfs.Data.Dirnames) 114 115 assert.True(bfs.IsData(filepath.Join(workingDir, "mydata", "file1.txt"))) 116 assert.True(bfs.IsI18n(filepath.Join(workingDir, "myi18n", "file1.txt"))) 117 assert.True(bfs.IsLayout(filepath.Join(workingDir, "mylayouts", "file1.txt"))) 118 assert.True(bfs.IsStatic(filepath.Join(workingDir, "mystatic", "file1.txt"))) 119 assert.True(bfs.IsAsset(filepath.Join(workingDir, "myassets", "file1.txt"))) 120 121 contentFilename := filepath.Join(workingDir, "mycontent", "file1.txt") 122 assert.True(bfs.IsContent(contentFilename)) 123 rel := bfs.RelContentDir(contentFilename) 124 assert.Equal("file1.txt", rel) 125 126 // Check Work fs vs theme 127 checkFileContent(bfs.Work.Fs, "file-root.txt", assert, "content-project") 128 checkFileContent(bfs.Work.Fs, "theme-root-atheme.txt", assert, "content:atheme") 129 130 } 131 132 func createConfig() *viper.Viper { 133 v := viper.New() 134 v.Set("contentDir", "mycontent") 135 v.Set("i18nDir", "myi18n") 136 v.Set("staticDir", "mystatic") 137 v.Set("dataDir", "mydata") 138 v.Set("layoutDir", "mylayouts") 139 v.Set("archetypeDir", "myarchetypes") 140 v.Set("assetDir", "myassets") 141 v.Set("resourceDir", "resources") 142 v.Set("publishDir", "public") 143 144 return v 145 } 146 147 func TestNewBaseFsEmpty(t *testing.T) { 148 assert := require.New(t) 149 v := createConfig() 150 fs := hugofs.NewMem(v) 151 p, err := paths.New(fs, v) 152 assert.NoError(err) 153 bfs, err := NewBase(p) 154 assert.NoError(err) 155 assert.NotNil(bfs) 156 assert.Equal(hugofs.NoOpFs, bfs.Archetypes.Fs) 157 assert.Equal(hugofs.NoOpFs, bfs.Layouts.Fs) 158 assert.Equal(hugofs.NoOpFs, bfs.Data.Fs) 159 assert.Equal(hugofs.NoOpFs, bfs.Assets.Fs) 160 assert.Equal(hugofs.NoOpFs, bfs.I18n.Fs) 161 assert.NotNil(bfs.Work.Fs) 162 assert.NotNil(bfs.Content.Fs) 163 assert.NotNil(bfs.Static) 164 } 165 166 func TestRealDirs(t *testing.T) { 167 assert := require.New(t) 168 v := createConfig() 169 fs := hugofs.NewDefault(v) 170 sfs := fs.Source 171 172 root, err := afero.TempDir(sfs, "", "realdir") 173 assert.NoError(err) 174 themesDir, err := afero.TempDir(sfs, "", "themesDir") 175 assert.NoError(err) 176 defer func() { 177 os.RemoveAll(root) 178 os.RemoveAll(themesDir) 179 }() 180 181 v.Set("workingDir", root) 182 v.Set("themesDir", themesDir) 183 v.Set("theme", "mytheme") 184 185 assert.NoError(sfs.MkdirAll(filepath.Join(root, "myassets", "scss", "sf1"), 0755)) 186 assert.NoError(sfs.MkdirAll(filepath.Join(root, "myassets", "scss", "sf2"), 0755)) 187 assert.NoError(sfs.MkdirAll(filepath.Join(themesDir, "mytheme", "assets", "scss", "sf2"), 0755)) 188 assert.NoError(sfs.MkdirAll(filepath.Join(themesDir, "mytheme", "assets", "scss", "sf3"), 0755)) 189 assert.NoError(sfs.MkdirAll(filepath.Join(root, "resources"), 0755)) 190 assert.NoError(sfs.MkdirAll(filepath.Join(themesDir, "mytheme", "resources"), 0755)) 191 192 assert.NoError(sfs.MkdirAll(filepath.Join(root, "myassets", "js", "f2"), 0755)) 193 194 afero.WriteFile(sfs, filepath.Join(filepath.Join(root, "myassets", "scss", "sf1", "a1.scss")), []byte("content"), 0755) 195 afero.WriteFile(sfs, filepath.Join(filepath.Join(root, "myassets", "scss", "sf2", "a3.scss")), []byte("content"), 0755) 196 afero.WriteFile(sfs, filepath.Join(filepath.Join(root, "myassets", "scss", "a2.scss")), []byte("content"), 0755) 197 afero.WriteFile(sfs, filepath.Join(filepath.Join(themesDir, "mytheme", "assets", "scss", "sf2", "a3.scss")), []byte("content"), 0755) 198 afero.WriteFile(sfs, filepath.Join(filepath.Join(themesDir, "mytheme", "assets", "scss", "sf3", "a4.scss")), []byte("content"), 0755) 199 200 afero.WriteFile(sfs, filepath.Join(filepath.Join(themesDir, "mytheme", "resources", "t1.txt")), []byte("content"), 0755) 201 afero.WriteFile(sfs, filepath.Join(filepath.Join(root, "resources", "p1.txt")), []byte("content"), 0755) 202 afero.WriteFile(sfs, filepath.Join(filepath.Join(root, "resources", "p2.txt")), []byte("content"), 0755) 203 204 afero.WriteFile(sfs, filepath.Join(filepath.Join(root, "myassets", "js", "f2", "a1.js")), []byte("content"), 0755) 205 afero.WriteFile(sfs, filepath.Join(filepath.Join(root, "myassets", "js", "a2.js")), []byte("content"), 0755) 206 207 p, err := paths.New(fs, v) 208 assert.NoError(err) 209 bfs, err := NewBase(p) 210 assert.NoError(err) 211 assert.NotNil(bfs) 212 checkFileCount(bfs.Assets.Fs, "", assert, 6) 213 214 realDirs := bfs.Assets.RealDirs("scss") 215 assert.Equal(2, len(realDirs)) 216 assert.Equal(filepath.Join(root, "myassets/scss"), realDirs[0]) 217 assert.Equal(filepath.Join(themesDir, "mytheme/assets/scss"), realDirs[len(realDirs)-1]) 218 219 checkFileCount(bfs.Resources.Fs, "", assert, 3) 220 221 } 222 223 func TestStaticFs(t *testing.T) { 224 assert := require.New(t) 225 v := createConfig() 226 workDir := "mywork" 227 v.Set("workingDir", workDir) 228 v.Set("themesDir", "themes") 229 v.Set("theme", "t1") 230 231 fs := hugofs.NewMem(v) 232 233 themeStaticDir := filepath.Join(workDir, "themes", "t1", "static") 234 235 afero.WriteFile(fs.Source, filepath.Join(workDir, "mystatic", "f1.txt"), []byte("Hugo Rocks!"), 0755) 236 afero.WriteFile(fs.Source, filepath.Join(themeStaticDir, "f1.txt"), []byte("Hugo Themes Rocks!"), 0755) 237 afero.WriteFile(fs.Source, filepath.Join(themeStaticDir, "f2.txt"), []byte("Hugo Themes Still Rocks!"), 0755) 238 239 p, err := paths.New(fs, v) 240 assert.NoError(err) 241 bfs, err := NewBase(p) 242 sfs := bfs.StaticFs("en") 243 checkFileContent(sfs, "f1.txt", assert, "Hugo Rocks!") 244 checkFileContent(sfs, "f2.txt", assert, "Hugo Themes Still Rocks!") 245 246 } 247 248 func TestStaticFsMultiHost(t *testing.T) { 249 assert := require.New(t) 250 v := createConfig() 251 workDir := "mywork" 252 v.Set("workingDir", workDir) 253 v.Set("themesDir", "themes") 254 v.Set("theme", "t1") 255 v.Set("multihost", true) 256 257 vn := viper.New() 258 vn.Set("staticDir", "nn_static") 259 260 en := langs.NewLanguage("en", v) 261 no := langs.NewLanguage("no", v) 262 no.Set("staticDir", "static_no") 263 264 languages := langs.Languages{ 265 en, 266 no, 267 } 268 269 v.Set("languagesSorted", languages) 270 271 fs := hugofs.NewMem(v) 272 273 themeStaticDir := filepath.Join(workDir, "themes", "t1", "static") 274 275 afero.WriteFile(fs.Source, filepath.Join(workDir, "mystatic", "f1.txt"), []byte("Hugo Rocks!"), 0755) 276 afero.WriteFile(fs.Source, filepath.Join(workDir, "static_no", "f1.txt"), []byte("Hugo Rocks in Norway!"), 0755) 277 278 afero.WriteFile(fs.Source, filepath.Join(themeStaticDir, "f1.txt"), []byte("Hugo Themes Rocks!"), 0755) 279 afero.WriteFile(fs.Source, filepath.Join(themeStaticDir, "f2.txt"), []byte("Hugo Themes Still Rocks!"), 0755) 280 281 p, err := paths.New(fs, v) 282 assert.NoError(err) 283 bfs, err := NewBase(p) 284 enFs := bfs.StaticFs("en") 285 checkFileContent(enFs, "f1.txt", assert, "Hugo Rocks!") 286 checkFileContent(enFs, "f2.txt", assert, "Hugo Themes Still Rocks!") 287 288 noFs := bfs.StaticFs("no") 289 checkFileContent(noFs, "f1.txt", assert, "Hugo Rocks in Norway!") 290 checkFileContent(noFs, "f2.txt", assert, "Hugo Themes Still Rocks!") 291 } 292 293 func checkFileCount(fs afero.Fs, dirname string, assert *require.Assertions, expected int) { 294 count, _, err := countFileaAndGetDirs(fs, dirname) 295 assert.NoError(err) 296 assert.Equal(expected, count) 297 } 298 299 func checkFileContent(fs afero.Fs, filename string, assert *require.Assertions, expected ...string) { 300 301 b, err := afero.ReadFile(fs, filename) 302 assert.NoError(err) 303 304 content := string(b) 305 306 for _, e := range expected { 307 assert.Contains(content, e) 308 } 309 } 310 311 func countFileaAndGetDirs(fs afero.Fs, dirname string) (int, []string, error) { 312 if fs == nil { 313 return 0, nil, errors.New("no fs") 314 } 315 316 counter := 0 317 var dirs []string 318 319 afero.Walk(fs, dirname, func(path string, info os.FileInfo, err error) error { 320 if info != nil { 321 if !info.IsDir() { 322 counter++ 323 } else if info.Name() != "." { 324 dirs = append(dirs, filepath.Join(path, info.Name())) 325 } 326 } 327 328 return nil 329 }) 330 331 return counter, dirs, nil 332 } 333 334 func setConfigAndWriteSomeFilesTo(fs afero.Fs, v *viper.Viper, key, val string, num int) { 335 workingDir := v.GetString("workingDir") 336 v.Set(key, val) 337 fs.Mkdir(val, 0755) 338 for i := 0; i < num; i++ { 339 afero.WriteFile(fs, filepath.Join(workingDir, val, fmt.Sprintf("file%d.txt", i+1)), []byte(fmt.Sprintf("content:%s:%d", key, i+1)), 0755) 340 } 341 }