From b8127fbb9c0c67019b97135f9c7766be68c06100 Mon Sep 17 00:00:00 2001 From: Walter Scheper Date: Tue, 10 Nov 2020 19:57:14 -0500 Subject: [PATCH] Add IPv4 and IPv6 generators These generators return `net.IP`, and are also used in generating URLs. --- ip_addr.go | 61 +++++++++++++++++++++++++++++++++++++++++ ip_addr_example_test.go | 46 +++++++++++++++++++++++++++++++ url.go | 20 ++++++++++---- url_example_test.go | 10 +++---- 4 files changed, 127 insertions(+), 10 deletions(-) create mode 100644 ip_addr.go create mode 100644 ip_addr_example_test.go diff --git a/ip_addr.go b/ip_addr.go new file mode 100644 index 0000000..13e24ec --- /dev/null +++ b/ip_addr.go @@ -0,0 +1,61 @@ +// Copyright 2020 Walter Scheper +// +// 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, + }) +} diff --git a/ip_addr_example_test.go b/ip_addr_example_test.go new file mode 100644 index 0000000..1379835 --- /dev/null +++ b/ip_addr_example_test.go @@ -0,0 +1,46 @@ +// Copyright 2020 Walter Scheper +// +// 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 +} diff --git a/url.go b/url.go index 8be1cee..4425b9f 100644 --- a/url.go +++ b/url.go @@ -8,6 +8,7 @@ package rapid import ( "fmt" + "net" "net/url" "reflect" "strings" @@ -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 { @@ -97,9 +107,9 @@ 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, } @@ -107,10 +117,10 @@ func (g *urlGenerator) value(t *T) value { // 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, }) diff --git a/url_example_test.go b/url_example_test.go index 6873e6d..8b5aabb 100644 --- a/url_example_test.go +++ b/url_example_test.go @@ -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+$ }