1package pgtype_test 2 3import ( 4 "net" 5 "reflect" 6 "testing" 7 8 "github.com/jackc/pgtype" 9 "github.com/jackc/pgtype/testutil" 10) 11 12func TestCIDRArrayTranscode(t *testing.T) { 13 testutil.TestSuccessfulTranscode(t, "cidr[]", []interface{}{ 14 &pgtype.CIDRArray{ 15 Elements: nil, 16 Dimensions: nil, 17 Status: pgtype.Present, 18 }, 19 &pgtype.CIDRArray{ 20 Elements: []pgtype.CIDR{ 21 {IPNet: mustParseCIDR(t, "12.34.56.0/32"), Status: pgtype.Present}, 22 {Status: pgtype.Null}, 23 }, 24 Dimensions: []pgtype.ArrayDimension{{Length: 2, LowerBound: 1}}, 25 Status: pgtype.Present, 26 }, 27 &pgtype.CIDRArray{Status: pgtype.Null}, 28 &pgtype.CIDRArray{ 29 Elements: []pgtype.CIDR{ 30 {IPNet: mustParseCIDR(t, "127.0.0.1/32"), Status: pgtype.Present}, 31 {IPNet: mustParseCIDR(t, "12.34.56.0/32"), Status: pgtype.Present}, 32 {IPNet: mustParseCIDR(t, "192.168.0.1/32"), Status: pgtype.Present}, 33 {IPNet: mustParseCIDR(t, "2607:f8b0:4009:80b::200e/128"), Status: pgtype.Present}, 34 {Status: pgtype.Null}, 35 {IPNet: mustParseCIDR(t, "255.0.0.0/8"), Status: pgtype.Present}, 36 }, 37 Dimensions: []pgtype.ArrayDimension{{Length: 3, LowerBound: 1}, {Length: 2, LowerBound: 1}}, 38 Status: pgtype.Present, 39 }, 40 &pgtype.CIDRArray{ 41 Elements: []pgtype.CIDR{ 42 {IPNet: mustParseCIDR(t, "127.0.0.1/32"), Status: pgtype.Present}, 43 {IPNet: mustParseCIDR(t, "12.34.56.0/32"), Status: pgtype.Present}, 44 {IPNet: mustParseCIDR(t, "192.168.0.1/32"), Status: pgtype.Present}, 45 {IPNet: mustParseCIDR(t, "2607:f8b0:4009:80b::200e/128"), Status: pgtype.Present}, 46 }, 47 Dimensions: []pgtype.ArrayDimension{ 48 {Length: 2, LowerBound: 4}, 49 {Length: 2, LowerBound: 2}, 50 }, 51 Status: pgtype.Present, 52 }, 53 }) 54} 55 56func TestCIDRArraySet(t *testing.T) { 57 successfulTests := []struct { 58 source interface{} 59 result pgtype.CIDRArray 60 }{ 61 { 62 source: []*net.IPNet{mustParseCIDR(t, "127.0.0.1/32")}, 63 result: pgtype.CIDRArray{ 64 Elements: []pgtype.CIDR{{IPNet: mustParseCIDR(t, "127.0.0.1/32"), Status: pgtype.Present}}, 65 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}}, 66 Status: pgtype.Present}, 67 }, 68 { 69 source: (([]*net.IPNet)(nil)), 70 result: pgtype.CIDRArray{Status: pgtype.Null}, 71 }, 72 { 73 source: []net.IP{mustParseCIDR(t, "127.0.0.1/32").IP}, 74 result: pgtype.CIDRArray{ 75 Elements: []pgtype.CIDR{{IPNet: mustParseCIDR(t, "127.0.0.1/32"), Status: pgtype.Present}}, 76 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}}, 77 Status: pgtype.Present}, 78 }, 79 { 80 source: (([]net.IP)(nil)), 81 result: pgtype.CIDRArray{Status: pgtype.Null}, 82 }, 83 { 84 source: [][]net.IP{{mustParseCIDR(t, "127.0.0.1/32").IP}, {mustParseCIDR(t, "10.0.0.1/32").IP}}, 85 result: pgtype.CIDRArray{ 86 Elements: []pgtype.CIDR{ 87 {IPNet: mustParseCIDR(t, "127.0.0.1/32"), Status: pgtype.Present}, 88 {IPNet: mustParseCIDR(t, "10.0.0.1/32"), Status: pgtype.Present}}, 89 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 2}, {LowerBound: 1, Length: 1}}, 90 Status: pgtype.Present}, 91 }, 92 { 93 source: [][][][]*net.IPNet{ 94 {{{ 95 mustParseCIDR(t, "127.0.0.1/24"), 96 mustParseCIDR(t, "10.0.0.1/24"), 97 mustParseCIDR(t, "172.16.0.1/16")}}}, 98 {{{ 99 mustParseCIDR(t, "192.168.0.1/16"), 100 mustParseCIDR(t, "224.0.0.1/24"), 101 mustParseCIDR(t, "169.168.0.1/16")}}}}, 102 result: pgtype.CIDRArray{ 103 Elements: []pgtype.CIDR{ 104 {IPNet: mustParseCIDR(t, "127.0.0.1/24"), Status: pgtype.Present}, 105 {IPNet: mustParseCIDR(t, "10.0.0.1/24"), Status: pgtype.Present}, 106 {IPNet: mustParseCIDR(t, "172.16.0.1/16"), Status: pgtype.Present}, 107 {IPNet: mustParseCIDR(t, "192.168.0.1/16"), Status: pgtype.Present}, 108 {IPNet: mustParseCIDR(t, "224.0.0.1/24"), Status: pgtype.Present}, 109 {IPNet: mustParseCIDR(t, "169.168.0.1/16"), Status: pgtype.Present}}, 110 Dimensions: []pgtype.ArrayDimension{ 111 {LowerBound: 1, Length: 2}, 112 {LowerBound: 1, Length: 1}, 113 {LowerBound: 1, Length: 1}, 114 {LowerBound: 1, Length: 3}}, 115 Status: pgtype.Present}, 116 }, 117 { 118 source: [2][1]net.IP{{mustParseCIDR(t, "127.0.0.1/32").IP}, {mustParseCIDR(t, "10.0.0.1/32").IP}}, 119 result: pgtype.CIDRArray{ 120 Elements: []pgtype.CIDR{ 121 {IPNet: mustParseCIDR(t, "127.0.0.1/32"), Status: pgtype.Present}, 122 {IPNet: mustParseCIDR(t, "10.0.0.1/32"), Status: pgtype.Present}}, 123 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 2}, {LowerBound: 1, Length: 1}}, 124 Status: pgtype.Present}, 125 }, 126 { 127 source: [2][1][1][3]*net.IPNet{ 128 {{{ 129 mustParseCIDR(t, "127.0.0.1/24"), 130 mustParseCIDR(t, "10.0.0.1/24"), 131 mustParseCIDR(t, "172.16.0.1/16")}}}, 132 {{{ 133 mustParseCIDR(t, "192.168.0.1/16"), 134 mustParseCIDR(t, "224.0.0.1/24"), 135 mustParseCIDR(t, "169.168.0.1/16")}}}}, 136 result: pgtype.CIDRArray{ 137 Elements: []pgtype.CIDR{ 138 {IPNet: mustParseCIDR(t, "127.0.0.1/24"), Status: pgtype.Present}, 139 {IPNet: mustParseCIDR(t, "10.0.0.1/24"), Status: pgtype.Present}, 140 {IPNet: mustParseCIDR(t, "172.16.0.1/16"), Status: pgtype.Present}, 141 {IPNet: mustParseCIDR(t, "192.168.0.1/16"), Status: pgtype.Present}, 142 {IPNet: mustParseCIDR(t, "224.0.0.1/24"), Status: pgtype.Present}, 143 {IPNet: mustParseCIDR(t, "169.168.0.1/16"), Status: pgtype.Present}}, 144 Dimensions: []pgtype.ArrayDimension{ 145 {LowerBound: 1, Length: 2}, 146 {LowerBound: 1, Length: 1}, 147 {LowerBound: 1, Length: 1}, 148 {LowerBound: 1, Length: 3}}, 149 Status: pgtype.Present}, 150 }, 151 } 152 153 for i, tt := range successfulTests { 154 var r pgtype.CIDRArray 155 err := r.Set(tt.source) 156 if err != nil { 157 t.Errorf("%d: %v", i, err) 158 } 159 160 if !reflect.DeepEqual(r, tt.result) { 161 t.Errorf("%d: expected %v to convert to %v, but it was %v", i, tt.source, tt.result, r) 162 } 163 } 164} 165 166func TestCIDRArrayAssignTo(t *testing.T) { 167 var ipnetSlice []*net.IPNet 168 var ipSlice []net.IP 169 var ipSliceDim2 [][]net.IP 170 var ipnetSliceDim4 [][][][]*net.IPNet 171 var ipArrayDim2 [2][1]net.IP 172 var ipnetArrayDim4 [2][1][1][3]*net.IPNet 173 174 simpleTests := []struct { 175 src pgtype.CIDRArray 176 dst interface{} 177 expected interface{} 178 }{ 179 { 180 src: pgtype.CIDRArray{ 181 Elements: []pgtype.CIDR{{IPNet: mustParseCIDR(t, "127.0.0.1/32"), Status: pgtype.Present}}, 182 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}}, 183 Status: pgtype.Present, 184 }, 185 dst: &ipnetSlice, 186 expected: []*net.IPNet{mustParseCIDR(t, "127.0.0.1/32")}, 187 }, 188 { 189 src: pgtype.CIDRArray{ 190 Elements: []pgtype.CIDR{{Status: pgtype.Null}}, 191 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}}, 192 Status: pgtype.Present, 193 }, 194 dst: &ipnetSlice, 195 expected: []*net.IPNet{nil}, 196 }, 197 { 198 src: pgtype.CIDRArray{ 199 Elements: []pgtype.CIDR{{IPNet: mustParseCIDR(t, "127.0.0.1/32"), Status: pgtype.Present}}, 200 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}}, 201 Status: pgtype.Present, 202 }, 203 dst: &ipSlice, 204 expected: []net.IP{mustParseCIDR(t, "127.0.0.1/32").IP}, 205 }, 206 { 207 src: pgtype.CIDRArray{ 208 Elements: []pgtype.CIDR{{Status: pgtype.Null}}, 209 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 1}}, 210 Status: pgtype.Present, 211 }, 212 dst: &ipSlice, 213 expected: []net.IP{nil}, 214 }, 215 { 216 src: pgtype.CIDRArray{Status: pgtype.Null}, 217 dst: &ipnetSlice, 218 expected: (([]*net.IPNet)(nil)), 219 }, 220 { 221 src: pgtype.CIDRArray{Status: pgtype.Present}, 222 dst: &ipnetSlice, 223 expected: []*net.IPNet{}, 224 }, 225 { 226 src: pgtype.CIDRArray{Status: pgtype.Null}, 227 dst: &ipSlice, 228 expected: (([]net.IP)(nil)), 229 }, 230 { 231 src: pgtype.CIDRArray{Status: pgtype.Present}, 232 dst: &ipSlice, 233 expected: []net.IP{}, 234 }, 235 { 236 src: pgtype.CIDRArray{ 237 Elements: []pgtype.CIDR{ 238 {IPNet: mustParseCIDR(t, "127.0.0.1/32"), Status: pgtype.Present}, 239 {IPNet: mustParseCIDR(t, "10.0.0.1/32"), Status: pgtype.Present}}, 240 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 2}, {LowerBound: 1, Length: 1}}, 241 Status: pgtype.Present}, 242 dst: &ipSliceDim2, 243 expected: [][]net.IP{{mustParseCIDR(t, "127.0.0.1/32").IP}, {mustParseCIDR(t, "10.0.0.1/32").IP}}, 244 }, 245 { 246 src: pgtype.CIDRArray{ 247 Elements: []pgtype.CIDR{ 248 {IPNet: mustParseCIDR(t, "127.0.0.1/24"), Status: pgtype.Present}, 249 {IPNet: mustParseCIDR(t, "10.0.0.1/24"), Status: pgtype.Present}, 250 {IPNet: mustParseCIDR(t, "172.16.0.1/16"), Status: pgtype.Present}, 251 {IPNet: mustParseCIDR(t, "192.168.0.1/16"), Status: pgtype.Present}, 252 {IPNet: mustParseCIDR(t, "224.0.0.1/24"), Status: pgtype.Present}, 253 {IPNet: mustParseCIDR(t, "169.168.0.1/16"), Status: pgtype.Present}}, 254 Dimensions: []pgtype.ArrayDimension{ 255 {LowerBound: 1, Length: 2}, 256 {LowerBound: 1, Length: 1}, 257 {LowerBound: 1, Length: 1}, 258 {LowerBound: 1, Length: 3}}, 259 Status: pgtype.Present}, 260 dst: &ipnetSliceDim4, 261 expected: [][][][]*net.IPNet{ 262 {{{ 263 mustParseCIDR(t, "127.0.0.1/24"), 264 mustParseCIDR(t, "10.0.0.1/24"), 265 mustParseCIDR(t, "172.16.0.1/16")}}}, 266 {{{ 267 mustParseCIDR(t, "192.168.0.1/16"), 268 mustParseCIDR(t, "224.0.0.1/24"), 269 mustParseCIDR(t, "169.168.0.1/16")}}}}, 270 }, 271 { 272 src: pgtype.CIDRArray{ 273 Elements: []pgtype.CIDR{ 274 {IPNet: mustParseCIDR(t, "127.0.0.1/32"), Status: pgtype.Present}, 275 {IPNet: mustParseCIDR(t, "10.0.0.1/32"), Status: pgtype.Present}}, 276 Dimensions: []pgtype.ArrayDimension{{LowerBound: 1, Length: 2}, {LowerBound: 1, Length: 1}}, 277 Status: pgtype.Present}, 278 dst: &ipArrayDim2, 279 expected: [2][1]net.IP{{mustParseCIDR(t, "127.0.0.1/32").IP}, {mustParseCIDR(t, "10.0.0.1/32").IP}}, 280 }, 281 { 282 src: pgtype.CIDRArray{ 283 Elements: []pgtype.CIDR{ 284 {IPNet: mustParseCIDR(t, "127.0.0.1/24"), Status: pgtype.Present}, 285 {IPNet: mustParseCIDR(t, "10.0.0.1/24"), Status: pgtype.Present}, 286 {IPNet: mustParseCIDR(t, "172.16.0.1/16"), Status: pgtype.Present}, 287 {IPNet: mustParseCIDR(t, "192.168.0.1/16"), Status: pgtype.Present}, 288 {IPNet: mustParseCIDR(t, "224.0.0.1/24"), Status: pgtype.Present}, 289 {IPNet: mustParseCIDR(t, "169.168.0.1/16"), Status: pgtype.Present}}, 290 Dimensions: []pgtype.ArrayDimension{ 291 {LowerBound: 1, Length: 2}, 292 {LowerBound: 1, Length: 1}, 293 {LowerBound: 1, Length: 1}, 294 {LowerBound: 1, Length: 3}}, 295 Status: pgtype.Present}, 296 dst: &ipnetArrayDim4, 297 expected: [2][1][1][3]*net.IPNet{ 298 {{{ 299 mustParseCIDR(t, "127.0.0.1/24"), 300 mustParseCIDR(t, "10.0.0.1/24"), 301 mustParseCIDR(t, "172.16.0.1/16")}}}, 302 {{{ 303 mustParseCIDR(t, "192.168.0.1/16"), 304 mustParseCIDR(t, "224.0.0.1/24"), 305 mustParseCIDR(t, "169.168.0.1/16")}}}}, 306 }, 307 } 308 309 for i, tt := range simpleTests { 310 err := tt.src.AssignTo(tt.dst) 311 if err != nil { 312 t.Errorf("%d: %v", i, err) 313 } 314 315 if dst := reflect.ValueOf(tt.dst).Elem().Interface(); !reflect.DeepEqual(dst, tt.expected) { 316 t.Errorf("%d: expected %v to assign %v, but result was %v", i, tt.src, tt.expected, dst) 317 } 318 } 319} 320