github.com/linchen2chris/hugo@v0.0.0-20230307053224-cec209389705/tpl/internal/go_templates/htmltemplate/url_test.go (about)

     1  // Copyright 2011 The Go Authors. 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  
     5  //go:build go1.13 && !windows
     6  // +build go1.13,!windows
     7  
     8  package template
     9  
    10  import (
    11  	"testing"
    12  )
    13  
    14  func TestURLNormalizer(t *testing.T) {
    15  	tests := []struct {
    16  		url, want string
    17  	}{
    18  		{"", ""},
    19  		{
    20  			"http://example.com:80/foo/bar?q=foo%20&bar=x+y#frag",
    21  			"http://example.com:80/foo/bar?q=foo%20&bar=x+y#frag",
    22  		},
    23  		{" ", "%20"},
    24  		{"%7c", "%7c"},
    25  		{"%7C", "%7C"},
    26  		{"%2", "%252"},
    27  		{"%", "%25"},
    28  		{"%z", "%25z"},
    29  		{"/foo|bar/%5c\u1234", "/foo%7cbar/%5c%e1%88%b4"},
    30  	}
    31  	for _, test := range tests {
    32  		if got := urlNormalizer(test.url); test.want != got {
    33  			t.Errorf("%q: want\n\t%q\nbut got\n\t%q", test.url, test.want, got)
    34  		}
    35  		if test.want != urlNormalizer(test.want) {
    36  			t.Errorf("not idempotent: %q", test.want)
    37  		}
    38  	}
    39  }
    40  
    41  func TestURLFilters(t *testing.T) {
    42  	input := ("\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f" +
    43  		"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" +
    44  		` !"#$%&'()*+,-./` +
    45  		`0123456789:;<=>?` +
    46  		`@ABCDEFGHIJKLMNO` +
    47  		`PQRSTUVWXYZ[\]^_` +
    48  		"`abcdefghijklmno" +
    49  		"pqrstuvwxyz{|}~\x7f" +
    50  		"\u00A0\u0100\u2028\u2029\ufeff\U0001D11E")
    51  
    52  	tests := []struct {
    53  		name    string
    54  		escaper func(...any) string
    55  		escaped string
    56  	}{
    57  		{
    58  			"urlEscaper",
    59  			urlEscaper,
    60  			"%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f" +
    61  				"%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f" +
    62  				"%20%21%22%23%24%25%26%27%28%29%2a%2b%2c-.%2f" +
    63  				"0123456789%3a%3b%3c%3d%3e%3f" +
    64  				"%40ABCDEFGHIJKLMNO" +
    65  				"PQRSTUVWXYZ%5b%5c%5d%5e_" +
    66  				"%60abcdefghijklmno" +
    67  				"pqrstuvwxyz%7b%7c%7d~%7f" +
    68  				"%c2%a0%c4%80%e2%80%a8%e2%80%a9%ef%bb%bf%f0%9d%84%9e",
    69  		},
    70  		{
    71  			"urlNormalizer",
    72  			urlNormalizer,
    73  			"%00%01%02%03%04%05%06%07%08%09%0a%0b%0c%0d%0e%0f" +
    74  				"%10%11%12%13%14%15%16%17%18%19%1a%1b%1c%1d%1e%1f" +
    75  				"%20!%22#$%25&%27%28%29*+,-./" +
    76  				"0123456789:;%3c=%3e?" +
    77  				"@ABCDEFGHIJKLMNO" +
    78  				"PQRSTUVWXYZ[%5c]%5e_" +
    79  				"%60abcdefghijklmno" +
    80  				"pqrstuvwxyz%7b%7c%7d~%7f" +
    81  				"%c2%a0%c4%80%e2%80%a8%e2%80%a9%ef%bb%bf%f0%9d%84%9e",
    82  		},
    83  	}
    84  
    85  	for _, test := range tests {
    86  		if s := test.escaper(input); s != test.escaped {
    87  			t.Errorf("%s: want\n\t%q\ngot\n\t%q", test.name, test.escaped, s)
    88  			continue
    89  		}
    90  	}
    91  }
    92  
    93  func TestSrcsetFilter(t *testing.T) {
    94  	tests := []struct {
    95  		name  string
    96  		input string
    97  		want  string
    98  	}{
    99  		{
   100  			"one ok",
   101  			"http://example.com/img.png",
   102  			"http://example.com/img.png",
   103  		},
   104  		{
   105  			"one ok with metadata",
   106  			" /img.png 200w",
   107  			" /img.png 200w",
   108  		},
   109  		{
   110  			"one bad",
   111  			"javascript:alert(1) 200w",
   112  			"#ZgotmplZ",
   113  		},
   114  		{
   115  			"two ok",
   116  			"foo.png, bar.png",
   117  			"foo.png, bar.png",
   118  		},
   119  		{
   120  			"left bad",
   121  			"javascript:alert(1), /foo.png",
   122  			"#ZgotmplZ, /foo.png",
   123  		},
   124  		{
   125  			"right bad",
   126  			"/bogus#, javascript:alert(1)",
   127  			"/bogus#,#ZgotmplZ",
   128  		},
   129  	}
   130  
   131  	for _, test := range tests {
   132  		if got := srcsetFilterAndEscaper(test.input); got != test.want {
   133  			t.Errorf("%s: srcsetFilterAndEscaper(%q) want %q != %q", test.name, test.input, test.want, got)
   134  		}
   135  	}
   136  }
   137  
   138  func BenchmarkURLEscaper(b *testing.B) {
   139  	for i := 0; i < b.N; i++ {
   140  		urlEscaper("http://example.com:80/foo?q=bar%20&baz=x+y#frag")
   141  	}
   142  }
   143  
   144  func BenchmarkURLEscaperNoSpecials(b *testing.B) {
   145  	for i := 0; i < b.N; i++ {
   146  		urlEscaper("TheQuickBrownFoxJumpsOverTheLazyDog.")
   147  	}
   148  }
   149  
   150  func BenchmarkURLNormalizer(b *testing.B) {
   151  	for i := 0; i < b.N; i++ {
   152  		urlNormalizer("The quick brown fox jumps over the lazy dog.\n")
   153  	}
   154  }
   155  
   156  func BenchmarkURLNormalizerNoSpecials(b *testing.B) {
   157  	for i := 0; i < b.N; i++ {
   158  		urlNormalizer("http://example.com:80/foo?q=bar%20&baz=x+y#frag")
   159  	}
   160  }
   161  
   162  func BenchmarkSrcsetFilter(b *testing.B) {
   163  	for i := 0; i < b.N; i++ {
   164  		srcsetFilterAndEscaper(" /foo/bar.png 200w, /baz/boo(1).png")
   165  	}
   166  }
   167  
   168  func BenchmarkSrcsetFilterNoSpecials(b *testing.B) {
   169  	for i := 0; i < b.N; i++ {
   170  		srcsetFilterAndEscaper("http://example.com:80/foo?q=bar%20&baz=x+y#frag")
   171  	}
   172  }