Skip to content

Commit

Permalink
URL generator also generates query and fragment
Browse files Browse the repository at this point in the history
To make the generated URL conform to how `url.Parse` works, Path
and Fragment are set to the unescaped form. RawPath and RawFragment
are left unset, and we simply rely on the URL struct to handle the
escaping as needed.
  • Loading branch information
wfscheper committed Nov 13, 2020
1 parent ad3b29a commit bd3833a
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 27 deletions.
15 changes: 9 additions & 6 deletions url.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ package rapid
import (
"fmt"
"net/url"
"path"
"reflect"
"strings"
"unicode"
)

Expand Down Expand Up @@ -79,6 +79,8 @@ func (g *urlGenerator) type_() reflect.Type {
return urlType
}

var printableGen = StringOf(RuneFrom(nil, unicode.PrintRanges...))

func (g *urlGenerator) value(t *T) value {
scheme := SampledFrom(g.schemes).Draw(t, "scheme").(string)
domain := Domain().Draw(t, "domain").(string)
Expand All @@ -90,15 +92,16 @@ func (g *urlGenerator) value(t *T) value {
return fmt.Sprintf(":%d", i)
}).
Draw(t, "port").(string)
path_ := path.Join(
SliceOf(
StringOf(RuneFrom(nil, unicode.PrintRanges...)).Map(url.PathEscape),
).Draw(t, "path").([]string)...)
path_ := SliceOf(printableGen).Draw(t, "path").([]string)
query := SliceOf(printableGen.Map(url.QueryEscape)).Draw(t, "query").([]string)
fragment := printableGen.Draw(t, "fragment").(string)

return url.URL{
Host: domain + port,
Path: path_,
Path: strings.Join(path_, "/"),
Scheme: scheme,
RawQuery: strings.Join(query, "&"),
Fragment: fragment,
}
}

Expand Down
8 changes: 4 additions & 4 deletions url_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ func ExampleURL() {
}

// Output:
// https://r125pz05Rz-0j1d-11.AArP:17
// http://L2.aBArTh:7/%25F0%259F%25AA%2595%2522%25D6%2593%25E0%25A9%25AD%25E1%25B3%25930%25D0%258A/%25C2%25BC%25E0%25B4%25BE3%25F0%259E%258B%25B0%25F0%2591%2586%25BD%25C2%25B2%25E0%25B3%25A9%25CC%2580D/%257C+%25F0%259F%2581%259D+%255D%25CC%2581%25CB%2585/%25CC%2580/%25E1%25B0%25BF/%25CD%2582K%25E0%25A5%25A9%25CC%2581
// https://pH20DR11.aaA
// http://h.AcCounTaNtS:4/%25F0%259E%25A5%259F/:%2521J%25E2%259D%2587
// https://r125pz05Rz-0j1d-11.AArP:17#0%E2%81%9B%F3%A0%84%9A
// http://L2.aBArTh:7/%F0%9F%AA%95%22%D6%93%E0%A9%AD%E1%B3%930%D0%8A/%C2%BC%E0%B4%BE3%F0%9E%8B%B0%F0%91%86%BD%C2%B2%E0%B3%A9%CC%80D/%7C+%F0%9F%81%9D+%5D%CC%81%CB%85/%CC%80/%E1%B0%BF/%CD%82K%E0%A5%A9%CC%81#%CC%82
// https://pH20DR11.aaA?%DB%97%F0%90%AC%BC%24%F0%91%99%83%E2%82%A5%F0%9D%A8%A8%E0%BC%95%E0%B5%A8%3C%E0%BE%B0%F0%97%8D%91%E2%9E%8E%E0%B9%91%24v%CC%80&%CC%94Z%E4%87%A4#%CC%A0%E1%81%AD
// http://h.AcCounTaNtS:4/%F0%9E%A5%9F/:%21J%E2%9D%87#L%CC%82%E9%98%A6%22
// http://A.xN--s9bRJ9C:2
}
17 changes: 0 additions & 17 deletions url_external_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,12 @@ package rapid_test

import (
"net/url"
"regexp"
"strings"
"testing"

. "pgregory.net/rapid"
)

var pathEscapeRegex = regexp.MustCompile(`^[0-9A-Fa-f]{2}`)

func TestURL(t *testing.T) {
t.Parallel()

Expand All @@ -27,20 +24,6 @@ func TestURL(t *testing.T) {
if _, err := url.Parse(u.String()); err != nil {
t.Fatalf("URL returned unparseable url %s: %v", u.String(), err)
}

// only valid characters in path
for i, ch := range u.Path {
if !(('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z') || ('0' <= ch && ch <= '9') || strings.ContainsRune("$-_.+!*'(),%/@=&:~", ch)) {
t.Fatalf("URL returned invalid url %s: invalid character %s at %d", u.String(), string(ch), i)
}
}

// assert proper path escapes
for _, co := range strings.Split(u.Path, "%")[1:] {
if ok := pathEscapeRegex.MatchString(co); !ok {
t.Fatalf("URL returned invalid url %s: invalid escape %s", u.String(), co)
}
}
})
}

Expand Down

0 comments on commit bd3833a

Please sign in to comment.