Skip to content

Commit

Permalink
Add IPv4 and IPv6 generators
Browse files Browse the repository at this point in the history
These generators return `net.IP`, and are also used in generating URLs.
  • Loading branch information
wfscheper committed Nov 11, 2020
1 parent 5bbc9c0 commit b8127fb
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 10 deletions.
61 changes: 61 additions & 0 deletions ip_addr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright 2020 Walter Scheper <walter.scheper@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

package rapid

import (
"fmt"
"net"
"reflect"
)

const (
ipv4Len = 4
ipv6Len = 16
)

var (
ipType = reflect.TypeOf(net.IP{})

ipv4Gen = SliceOfN(Byte(), ipv4Len, ipv4Len)
ipv6Gen = SliceOfN(Byte(), ipv6Len, ipv6Len)
)

type ipGen struct {
ipv6 bool
}

func (g *ipGen) String() string {
return fmt.Sprintf("IP(ipv6=%v)", g.ipv6)
}

func (*ipGen) type_() reflect.Type {
return ipType
}

func (g *ipGen) value(t *T) value {
var gen *Generator
if g.ipv6 {
gen = ipv6Gen
} else {
gen = ipv4Gen
}

b := gen.Draw(t, g.String()).([]byte)
return net.IP(b)
}

func IPv4() *Generator {
return newGenerator(&ipGen{
ipv6: false,
})
}

func IPv6() *Generator {
return newGenerator(&ipGen{
ipv6: true,
})
}
46 changes: 46 additions & 0 deletions ip_addr_example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright 2020 Walter Scheper <walter.scheper@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

package rapid_test

import (
"fmt"
"net"

"pgregory.net/rapid"
)

func ExampleIPv4() {
gen := rapid.IPv4()

for i := 0; i < 5; i++ {
addr := gen.Example(i).(net.IP)
fmt.Println(addr.String())
}

// Output:
// 0.23.24.7
// 100.146.0.0
// 0.222.65.1
// 1.49.104.14
// 11.56.0.83
}

func ExampleIPv6() {
gen := rapid.IPv6()

for i := 0; i < 5; i++ {
addr := gen.Example(i).(net.IP)
fmt.Println(addr.String())
}

// Output:
// 17:1807:e2c4:8210:7202:f4b2:a0e2:8dc
// 6492:0:fa37:b00:b5c3:4e6:6a01:c802
// de:4101:9f5:3:104:5dc:b600:905
// 131:680e:97ff:d200:ae1:4d00:2300:103
// b38:53:ff07:200:8c28:ee:ad00:1b
}
20 changes: 15 additions & 5 deletions url.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package rapid

import (
"fmt"
"net"
"net/url"
"reflect"
"strings"
Expand Down Expand Up @@ -83,7 +84,16 @@ 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)
var domain string
switch SampledFrom([]int{0, 1, 2}).Draw(t, "g").(int) {
case 2:
domain = Domain().Draw(t, "domain").(string)
case 1:
domain = IPv6().Draw(t, "domain").(net.IP).String()
domain = "[" + domain + "]"
case 0:
domain = IPv4().Draw(t, "domain").(net.IP).String()
}
port := IntRange(0, 2^16-1).
Map(func(i int) string {
if i == 0 {
Expand All @@ -97,20 +107,20 @@ func (g *urlGenerator) value(t *T) value {
fragment := printableGen.Draw(t, "fragment").(string)

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

// URL generates RFC 3986 compliant http/https URLs.
func URL() *Generator {
return urlOf([]string{"http", "https"})
return urlOf([]string{"http", "https"}, Domain())
}

func urlOf(schemes []string) *Generator {
func urlOf(schemes []string, domain *Generator) *Generator {
return newGenerator(&urlGenerator{
schemes: schemes,
})
Expand Down
10 changes: 5 additions & 5 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#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
// https://[e506:816b:407:316:fb4c:ffa0:e208:dc0e]/%F0%97%B3%80%F0%92%91%ADX/1=%22?%C4%90%F0%90%A9%87%26#%F0%91%B2%9E1%CC%88%CC%81D
// http://G.BLoG/%E0%AD%8C~%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://1.47.4.5:11/+%3E%E2%9F%BCK//A%DB%97%F0%90%AC%BC$%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$v%CC%80/%CC%94Z%E4%87%A4?%F0%91%91%9BC%C2%B9%E2%8A%A5%F0%91%91%8F1%E0%A0%BE%CB%BE%C3%9D%E1%B3%A8%E0%AB%A6%CC%81%CC%86&%E2%A4%88%F0%91%8A%A9%24B%F0%9D%8B%AA%CC%9A&&%CC%80%C2%A7%E4%92%9B&#%E0%AB%AE%F0%92%91%A2
// http://G.hM/%CC%80%E0%A0%B1%CC%82%CC%80%F0%9E%A5%9F/:%21J%E2%9D%87#L%CC%82%E9%98%A6%22
// http://1.1.4.6:2/%E3%B5%B8%C3%B2%DE%A6%E1%9E%B9/%C2%A7/?%E2%80%A60%CC%80%C3%B7&%CC%81%CC%A2%21%E0%AF%AB%CC%81%C3%A4&%F0%9F%AA%95%EA%99%B4%CC%80%E0%A5%AD&%F0%AD%B9%A9%F0%91%87%AE&&%E1%B7%93%CC%8B%E2%87%94%E2%90%8E%EA%A3%A5%E0%B5%9A%3D%E5%8E%A4%D9%AAB%F0%A5%8F%9A%3D%C2%A4%C3%AE%F0%91%84%AD%DC%8A%21%E2%82%8D3&%E1%81%8F%23#%CC%80%E0%BF%8B+$
}

0 comments on commit b8127fb

Please sign in to comment.