github.com/hhsnopek/up@v0.1.1/internal/redirect/redirect_test.go (about)

     1  package redirect
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/tj/assert"
     8  )
     9  
    10  func rule(from, to string) Rule {
    11  	r := Rule{
    12  		Path:     from,
    13  		Location: to,
    14  	}
    15  
    16  	r.Compile()
    17  	return r
    18  }
    19  
    20  func TestRule_URL(t *testing.T) {
    21  	t.Run("exact", func(t *testing.T) {
    22  		s := rule("/docs", "/help").URL("/docs")
    23  		assert.Equal(t, "/help", s)
    24  	})
    25  
    26  	t.Run("splat one segment", func(t *testing.T) {
    27  		r := rule("/docs/*", "/help/:splat")
    28  		assert.Equal(t, "/help/foo", r.URL("/docs/foo"))
    29  	})
    30  
    31  	t.Run("splat many segments", func(t *testing.T) {
    32  		r := rule("/docs/*", "/help/:splat")
    33  		assert.Equal(t, "/help/foo/bar/baz", r.URL("/docs/foo/bar/baz"))
    34  	})
    35  
    36  	t.Run("placeholder", func(t *testing.T) {
    37  		r := rule("/shop/:brand", "/store/:brand")
    38  		assert.Equal(t, "/store/apple", r.URL("/shop/apple"))
    39  	})
    40  
    41  	t.Run("placeholders", func(t *testing.T) {
    42  		r := rule("/shop/:brand/category/:cat", "/products/:brand/:cat")
    43  		assert.Equal(t, "/products/apple/laptops", r.URL("/shop/apple/category/laptops"))
    44  	})
    45  
    46  	t.Run("placeholders trailing slash", func(t *testing.T) {
    47  		r := rule("/docs/:product/guides/:guide", "/help/:product/:guide")
    48  		assert.Equal(t, "/help/ping/alerting", r.URL("/docs/ping/guides/alerting/"))
    49  	})
    50  
    51  	t.Run("placeholders rearranged", func(t *testing.T) {
    52  		r := rule("/shop/:brand/category/:cat", "/products/:cat/:brand")
    53  		assert.Equal(t, "/products/laptops/apple", r.URL("/shop/apple/category/laptops"))
    54  	})
    55  
    56  	t.Run("placeholders mismatch", func(t *testing.T) {
    57  		// TODO: sorry :D
    58  		err := func() (err error) {
    59  			defer func() {
    60  				err = recover().(error)
    61  			}()
    62  
    63  			rule("/shop/:brand/category/:category", "/products/:cat/:brand")
    64  			return nil
    65  		}()
    66  
    67  		assert.EqualError(t, err, `placeholder ":cat" is not present in the path pattern "/shop/:brand/category/:category"`)
    68  	})
    69  }
    70  
    71  func TestMatcher_Lookup(t *testing.T) {
    72  	rules := Rules{
    73  		"/docs/:product/guides/:guide": Rule{
    74  			Location: "/help/:product/:guide",
    75  			Status:   301,
    76  		},
    77  		"/blog": Rule{
    78  			Location: "https://blog.apex.sh",
    79  			Status:   302,
    80  		},
    81  		"/articles/*": Rule{
    82  			Location: "/guides/:splat",
    83  		},
    84  	}
    85  
    86  	m, err := Compile(rules)
    87  	assert.NoError(t, err, "compile")
    88  
    89  	t.Run("exact", func(t *testing.T) {
    90  		assert.NotNil(t, m.Lookup("/blog"))
    91  	})
    92  
    93  	t.Run("exact trailing slash", func(t *testing.T) {
    94  		assert.NotNil(t, m.Lookup("/blog/"))
    95  	})
    96  
    97  	t.Run("placeholders", func(t *testing.T) {
    98  		assert.NotNil(t, m.Lookup("/docs/ping/guides/alerts"))
    99  	})
   100  
   101  	// TODO: need to fork the trie to be less greedy
   102  	// t.Run("mismatch", func(t *testing.T) {
   103  	// 	r := m.Lookup("/docs/ping/another/guides/alerts")
   104  	// 	assert.NotNil(t, r)
   105  	// })
   106  
   107  	t.Run("splat one segment", func(t *testing.T) {
   108  		assert.NotNil(t, m.Lookup("/articles/alerting"))
   109  	})
   110  
   111  	t.Run("splat many segments", func(t *testing.T) {
   112  		assert.NotNil(t, m.Lookup("/articles/alerting/pagerduty"))
   113  		assert.NotNil(t, m.Lookup("/articles/alerting/pagerduty/"))
   114  	})
   115  }
   116  
   117  func BenchmarkMatcher_Lookup(b *testing.B) {
   118  	rules := Rules{
   119  		"/docs/:product/guides/:guide": Rule{
   120  			Location: "/help/:product/:guide",
   121  			Status:   301,
   122  		},
   123  	}
   124  
   125  	m, err := Compile(rules)
   126  	assert.NoError(b, err, "compile")
   127  
   128  	b.ResetTimer()
   129  
   130  	b.Run("match", func(b *testing.B) {
   131  		for i := 0; i < b.N; i++ {
   132  			fmt.Printf("%#v\n", m.Lookup("/docs/ping/guides/alerts"))
   133  		}
   134  	})
   135  
   136  	b.Run("mismatch", func(b *testing.B) {
   137  		for i := 0; i < b.N; i++ {
   138  			m.Lookup("/some/other/page")
   139  		}
   140  	})
   141  }