2017-01-10 04:55:03 -05:00
package hugolib
import (
"path/filepath"
"testing"
2017-02-17 14:52:50 -05:00
"regexp"
"fmt"
"strings"
2017-06-13 12:42:45 -04:00
"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/deps"
2017-06-13 13:07:35 -04:00
"github.com/spf13/afero"
2017-02-20 03:33:35 -05:00
2017-06-13 12:42:45 -04:00
"github.com/gohugoio/hugo/helpers"
"github.com/gohugoio/hugo/tpl"
2017-01-10 04:55:03 -05:00
"github.com/spf13/viper"
2017-02-04 22:20:06 -05:00
"io/ioutil"
"os"
"log"
2017-06-13 12:42:45 -04:00
"github.com/gohugoio/hugo/hugofs"
2017-02-04 22:20:06 -05:00
jww "github.com/spf13/jwalterweatherman"
2017-01-10 04:55:03 -05:00
"github.com/stretchr/testify/require"
)
2017-02-17 14:52:50 -05:00
type testHelper struct {
Cfg config . Provider
Fs * hugofs . Fs
T testing . TB
}
2017-02-17 15:14:52 -05:00
func ( th testHelper ) assertFileContent ( filename string , matches ... string ) {
filename = th . replaceDefaultContentLanguageValue ( filename )
2017-02-17 14:52:50 -05:00
content := readDestination ( th . T , th . Fs , filename )
for _ , match := range matches {
2017-02-17 15:14:52 -05:00
match = th . replaceDefaultContentLanguageValue ( match )
2017-02-17 14:52:50 -05:00
require . True ( th . T , strings . Contains ( content , match ) , fmt . Sprintf ( "File no match for\n%q in\n%q:\n%s" , strings . Replace ( match , "%" , "%%" , - 1 ) , filename , strings . Replace ( content , "%" , "%%" , - 1 ) ) )
}
}
2017-02-17 15:14:52 -05:00
// TODO(bep) better name for this. It does no magic replacements depending on defaultontentLanguageInSubDir.
func ( th testHelper ) assertFileContentStraight ( filename string , matches ... string ) {
2017-02-17 14:52:50 -05:00
content := readDestination ( th . T , th . Fs , filename )
for _ , match := range matches {
2017-02-17 15:14:52 -05:00
require . True ( th . T , strings . Contains ( content , match ) , fmt . Sprintf ( "File no match for\n%q in\n%q:\n%s" , strings . Replace ( match , "%" , "%%" , - 1 ) , filename , strings . Replace ( content , "%" , "%%" , - 1 ) ) )
}
}
func ( th testHelper ) assertFileContentRegexp ( filename string , matches ... string ) {
filename = th . replaceDefaultContentLanguageValue ( filename )
content := readDestination ( th . T , th . Fs , filename )
for _ , match := range matches {
match = th . replaceDefaultContentLanguageValue ( match )
2017-02-17 14:52:50 -05:00
r := regexp . MustCompile ( match )
require . True ( th . T , r . MatchString ( content ) , fmt . Sprintf ( "File no match for\n%q in\n%q:\n%s" , strings . Replace ( match , "%" , "%%" , - 1 ) , filename , strings . Replace ( content , "%" , "%%" , - 1 ) ) )
}
}
2017-04-23 16:03:25 -04:00
func ( th testHelper ) assertFileNotExist ( filename string ) {
exists , err := helpers . Exists ( filename , th . Fs . Destination )
require . NoError ( th . T , err )
require . False ( th . T , exists )
}
2017-02-17 15:14:52 -05:00
func ( th testHelper ) replaceDefaultContentLanguageValue ( value string ) string {
defaultInSubDir := th . Cfg . GetBool ( "defaultContentLanguageInSubDir" )
replace := th . Cfg . GetString ( "defaultContentLanguage" ) + "/"
if ! defaultInSubDir {
value = strings . Replace ( value , replace , "" , 1 )
}
return value
}
2017-02-04 22:20:06 -05:00
func newTestPathSpec ( fs * hugofs . Fs , v * viper . Viper ) * helpers . PathSpec {
l := helpers . NewDefaultLanguage ( v )
2017-03-25 09:37:04 -04:00
ps , _ := helpers . NewPathSpec ( fs , l )
return ps
2017-01-10 04:55:03 -05:00
}
2017-03-09 13:19:29 -05:00
func newTestDefaultPathSpec ( ) * helpers . PathSpec {
v := viper . New ( )
// Easier to reason about in tests.
v . Set ( "disablePathToLower" , true )
fs := hugofs . NewDefault ( v )
2017-03-25 09:37:04 -04:00
ps , _ := helpers . NewPathSpec ( fs , v )
return ps
2017-03-09 13:19:29 -05:00
}
2017-02-04 22:20:06 -05:00
func newTestCfg ( ) ( * viper . Viper , * hugofs . Fs ) {
v := viper . New ( )
fs := hugofs . NewMem ( v )
v . SetFs ( fs . Source )
loadDefaultSettingsFor ( v )
// Default is false, but true is easier to use as default in tests
v . Set ( "defaultContentLanguageInSubdir" , true )
return v , fs
}
// newTestSite creates a new site in the English language with in-memory Fs.
// The site will have a template system loaded and ready to use.
// Note: This is only used in single site tests.
func newTestSite ( t testing . TB , configKeyValues ... interface { } ) * Site {
cfg , fs := newTestCfg ( )
for i := 0 ; i < len ( configKeyValues ) ; i += 2 {
cfg . Set ( configKeyValues [ i ] . ( string ) , configKeyValues [ i + 1 ] )
}
2017-03-06 13:54:46 -05:00
d := deps . DepsCfg { Language : helpers . NewLanguage ( "en" , cfg ) , Fs : fs , Cfg : cfg }
2017-02-04 22:20:06 -05:00
s , err := NewSiteForCfg ( d )
if err != nil {
t . Fatalf ( "Failed to create Site: %s" , err )
}
return s
}
2017-03-27 14:43:49 -04:00
func newTestSitesFromConfig ( t testing . TB , afs afero . Fs , tomlConfig string , layoutPathContentPairs ... string ) ( testHelper , * HugoSites ) {
2017-02-20 03:33:35 -05:00
if len ( layoutPathContentPairs ) % 2 != 0 {
t . Fatalf ( "Layouts must be provided in pairs" )
}
2017-03-27 14:43:49 -04:00
writeToFs ( t , afs , "config.toml" , tomlConfig )
2017-02-20 03:33:35 -05:00
2017-03-27 14:43:49 -04:00
cfg , err := LoadConfig ( afs , "" , "config.toml" )
2017-02-20 03:33:35 -05:00
require . NoError ( t , err )
2017-03-27 14:43:49 -04:00
fs := hugofs . NewFrom ( afs , cfg )
2017-02-20 03:33:35 -05:00
th := testHelper { cfg , fs , t }
for i := 0 ; i < len ( layoutPathContentPairs ) ; i += 2 {
writeSource ( t , fs , layoutPathContentPairs [ i ] , layoutPathContentPairs [ i + 1 ] )
}
h , err := NewHugoSites ( deps . DepsCfg { Fs : fs , Cfg : cfg } )
require . NoError ( t , err )
return th , h
}
func newTestSitesFromConfigWithDefaultTemplates ( t testing . TB , tomlConfig string ) ( testHelper , * HugoSites ) {
2017-03-27 14:43:49 -04:00
return newTestSitesFromConfig ( t , afero . NewMemMapFs ( ) , tomlConfig ,
2017-02-20 03:33:35 -05:00
"layouts/_default/single.html" , "Single|{{ .Title }}|{{ .Content }}" ,
"layouts/_default/list.html" , "List|{{ .Title }}|{{ .Content }}" ,
"layouts/_default/terms.html" , "Terms List|{{ .Title }}|{{ .Content }}" ,
)
}
2017-02-04 22:20:06 -05:00
func newDebugLogger ( ) * jww . Notepad {
return jww . NewNotepad ( jww . LevelDebug , jww . LevelError , os . Stdout , ioutil . Discard , "" , log . Ldate | log . Ltime )
2017-01-10 04:55:03 -05:00
}
2017-03-03 04:47:43 -05:00
func newErrorLogger ( ) * jww . Notepad {
return jww . NewNotepad ( jww . LevelError , jww . LevelError , os . Stdout , ioutil . Discard , "" , log . Ldate | log . Ltime )
}
:sparkles: Implement Page bundling and image handling
This commit is not the smallest in Hugo's history.
Some hightlights include:
* Page bundles (for complete articles, keeping images and content together etc.).
* Bundled images can be processed in as many versions/sizes as you need with the three methods `Resize`, `Fill` and `Fit`.
* Processed images are cached inside `resources/_gen/images` (default) in your project.
* Symbolic links (both files and dirs) are now allowed anywhere inside /content
* A new table based build summary
* The "Total in nn ms" now reports the total including the handling of the files inside /static. So if it now reports more than you're used to, it is just **more real** and probably faster than before (see below).
A site building benchmark run compared to `v0.31.1` shows that this should be slightly faster and use less memory:
```bash
▶ ./benchSite.sh "TOML,num_langs=.*,num_root_sections=5,num_pages=(500|1000),tags_per_page=5,shortcodes,render"
benchmark old ns/op new ns/op delta
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 101785785 78067944 -23.30%
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 185481057 149159919 -19.58%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 103149918 85679409 -16.94%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 203515478 169208775 -16.86%
benchmark old allocs new allocs delta
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 532464 391539 -26.47%
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 1056549 772702 -26.87%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 555974 406630 -26.86%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 1086545 789922 -27.30%
benchmark old bytes new bytes delta
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 53243246 43598155 -18.12%
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 105811617 86087116 -18.64%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 54558852 44545097 -18.35%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 106903858 86978413 -18.64%
```
Fixes #3651
Closes #3158
Fixes #1014
Closes #2021
Fixes #1240
Updates #3757
2017-07-24 03:00:23 -04:00
func newWarningLogger ( ) * jww . Notepad {
return jww . NewNotepad ( jww . LevelWarn , jww . LevelError , os . Stdout , ioutil . Discard , "" , log . Ldate | log . Ltime )
}
2017-03-27 14:43:49 -04:00
func createWithTemplateFromNameValues ( additionalTemplates ... string ) func ( templ tpl . TemplateHandler ) error {
2017-01-10 04:55:03 -05:00
2017-03-27 14:43:49 -04:00
return func ( templ tpl . TemplateHandler ) error {
2017-01-10 04:55:03 -05:00
for i := 0 ; i < len ( additionalTemplates ) ; i += 2 {
err := templ . AddTemplate ( additionalTemplates [ i ] , additionalTemplates [ i + 1 ] )
if err != nil {
return err
}
}
return nil
}
}
2017-05-23 05:10:15 -04:00
func buildSingleSite ( t testing . TB , depsCfg deps . DepsCfg , buildCfg BuildCfg ) * Site {
2017-02-04 22:20:06 -05:00
return buildSingleSiteExpected ( t , false , depsCfg , buildCfg )
}
2017-05-23 05:10:15 -04:00
func buildSingleSiteExpected ( t testing . TB , expectBuildError bool , depsCfg deps . DepsCfg , buildCfg BuildCfg ) * Site {
2017-02-04 22:20:06 -05:00
h , err := NewHugoSites ( depsCfg )
2017-01-10 04:55:03 -05:00
require . NoError ( t , err )
require . Len ( t , h . Sites , 1 )
2017-02-04 22:20:06 -05:00
if expectBuildError {
require . Error ( t , h . Build ( buildCfg ) )
return nil
}
2017-01-10 04:55:03 -05:00
require . NoError ( t , h . Build ( buildCfg ) )
return h . Sites [ 0 ]
}
:sparkles: Implement Page bundling and image handling
This commit is not the smallest in Hugo's history.
Some hightlights include:
* Page bundles (for complete articles, keeping images and content together etc.).
* Bundled images can be processed in as many versions/sizes as you need with the three methods `Resize`, `Fill` and `Fit`.
* Processed images are cached inside `resources/_gen/images` (default) in your project.
* Symbolic links (both files and dirs) are now allowed anywhere inside /content
* A new table based build summary
* The "Total in nn ms" now reports the total including the handling of the files inside /static. So if it now reports more than you're used to, it is just **more real** and probably faster than before (see below).
A site building benchmark run compared to `v0.31.1` shows that this should be slightly faster and use less memory:
```bash
▶ ./benchSite.sh "TOML,num_langs=.*,num_root_sections=5,num_pages=(500|1000),tags_per_page=5,shortcodes,render"
benchmark old ns/op new ns/op delta
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 101785785 78067944 -23.30%
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 185481057 149159919 -19.58%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 103149918 85679409 -16.94%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 203515478 169208775 -16.86%
benchmark old allocs new allocs delta
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 532464 391539 -26.47%
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 1056549 772702 -26.87%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 555974 406630 -26.86%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 1086545 789922 -27.30%
benchmark old bytes new bytes delta
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 53243246 43598155 -18.12%
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 105811617 86087116 -18.64%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 54558852 44545097 -18.35%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 106903858 86978413 -18.64%
```
Fixes #3651
Closes #3158
Fixes #1014
Closes #2021
Fixes #1240
Updates #3757
2017-07-24 03:00:23 -04:00
func writeSourcesToSource ( t * testing . T , base string , fs * hugofs . Fs , sources ... [ 2 ] string ) {
2017-01-10 04:55:03 -05:00
for _ , src := range sources {
:sparkles: Implement Page bundling and image handling
This commit is not the smallest in Hugo's history.
Some hightlights include:
* Page bundles (for complete articles, keeping images and content together etc.).
* Bundled images can be processed in as many versions/sizes as you need with the three methods `Resize`, `Fill` and `Fit`.
* Processed images are cached inside `resources/_gen/images` (default) in your project.
* Symbolic links (both files and dirs) are now allowed anywhere inside /content
* A new table based build summary
* The "Total in nn ms" now reports the total including the handling of the files inside /static. So if it now reports more than you're used to, it is just **more real** and probably faster than before (see below).
A site building benchmark run compared to `v0.31.1` shows that this should be slightly faster and use less memory:
```bash
▶ ./benchSite.sh "TOML,num_langs=.*,num_root_sections=5,num_pages=(500|1000),tags_per_page=5,shortcodes,render"
benchmark old ns/op new ns/op delta
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 101785785 78067944 -23.30%
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 185481057 149159919 -19.58%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 103149918 85679409 -16.94%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 203515478 169208775 -16.86%
benchmark old allocs new allocs delta
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 532464 391539 -26.47%
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 1056549 772702 -26.87%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 555974 406630 -26.86%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 1086545 789922 -27.30%
benchmark old bytes new bytes delta
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 53243246 43598155 -18.12%
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 105811617 86087116 -18.64%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 54558852 44545097 -18.35%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 106903858 86978413 -18.64%
```
Fixes #3651
Closes #3158
Fixes #1014
Closes #2021
Fixes #1240
Updates #3757
2017-07-24 03:00:23 -04:00
writeSource ( t , fs , filepath . Join ( base , src [ 0 ] ) , src [ 1 ] )
}
}
func dumpPages ( pages ... * Page ) {
for i , p := range pages {
fmt . Printf ( "%d: Kind: %s Title: %-10s RelPermalink: %-10s Path: %-10s sections: %s Len Sections(): %d\n" ,
i + 1 ,
p . Kind , p . Title , p . RelPermalink ( ) , p . Path ( ) , p . sections , len ( p . Sections ( ) ) )
2017-01-10 04:55:03 -05:00
}
}
2017-06-13 15:22:47 -04:00
func isCI ( ) bool {
return os . Getenv ( "CI" ) != ""
}