Skip to content

Commit

Permalink
Merge pull request #75 from mfalesni/ip-addr-prefix
Browse files Browse the repository at this point in the history
Enable passing a prefix for IP addresses
  • Loading branch information
omaciel committed May 28, 2015
2 parents 6f7af0c + 048715d commit f2f62a4
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 8 deletions.
1 change: 1 addition & 0 deletions AUTHORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ Contributors
- Jonathan Edwards `@apense <https://github.com/apense/>`_
- Kedar Bidarkar `@kbidarkar <https://github.com/kbidarkar/>`_
- Sachin Ghai `@sghai <https://github.com/sghai/>`_
- Milan Falešník `@mfalesni <https://github.com/mfalesni/>`_
42 changes: 35 additions & 7 deletions fauxfactory/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -520,25 +520,53 @@ def gen_negative_integer():
return gen_integer(max_value=max_value)


def gen_ipaddr(ip3=False, ipv6=False):
def gen_ipaddr(ip3=False, ipv6=False, prefix=()):
"""Generates a random IP address.
You can also specify an IP address prefix if you are interested in
local network address generation, etc.
:param bool ip3: Whether to generate a 3 or 4 group IP.
:param bool ipv6: Whether to generate IPv6 or IPv4
:param list prefix: A prefix to be used for IPv4 (like [10, 0, 1]). It
must be an iterable with strings or integers. Can be left unspecified or
empty.
:returns: An IP address.
:rtype: str
:raises: ``ValueError`` if ``prefix`` would lead to no random fields at all.
This means the length that triggers the ``ValueError`` is 4 for regular
IPv4, 3 for IPv4 with ip3 and 8 for IPv6. It will be raised in any case
the prefix length reaches or exceeds those values.
"""

# Set the lengths of the randomly generated sections
if ipv6:
rng = 8
elif ip3:
rng = 3
else:
rng = 4
prefix = [str(field) for field in prefix]
# Prefix reduces number of random fields generated, so subtract the length
# of it from the rng to keep the IP address have correct number of fields
rng -= len(prefix)
if rng == 0:
raise ValueError(
"Prefix {} would lead to no randomness at all".format(
repr(prefix)))
elif rng < 0:
raise ValueError(
"Prefix {} is too long for this configuration".format(
repr(prefix)))
if ipv6:
# StackOverflow.com questions: generate-random-ipv6-address
ipaddr = u':'.join('{0:x}'.format(
random.randint(0, 2**16 - 1)
) for i in range(8))
random_fields = [
'{0:x}'.format(random.randint(0, 2**16 - 1)) for _ in range(rng)]
ipaddr = u':'.join(prefix + random_fields)
else:
rng = 3 if ip3 else 4
ipaddr = u".".join(
str(random.randrange(0, 255, 1)) for x in range(rng))
random_fields = [str(random.randrange(0, 255, 1)) for _ in range(rng)]
ipaddr = u".".join(prefix + random_fields)

if ip3:
ipaddr = ipaddr + u".0"
Expand Down
4 changes: 3 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
# setuptools is preferred over distutils. See:
# https://packaging.python.org/en/latest/current.html#packaging-tool-recommendations
from setuptools import find_packages, setup
import codecs
import os


def read(*paths):
"""Build a file path from *paths* and return the contents."""
with open(os.path.join(*paths), 'r') as handle:
filename = os.path.join(*paths)
with codecs.open(filename, mode='r', encoding="utf-8") as handle:
return handle.read()

LONG_DESCRIPTION = (read('README.rst') + '\n\n' +
Expand Down
142 changes: 142 additions & 0 deletions tests/test_ipaddress.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,99 @@ def test_gen_ipv4_4(self):
len(result.split(".")) == 4,
"Did not generate a 4-group IPv4 addrss")

def test_gen_ipv4_5(self):
"""
@Test: Generate a 4 group IPv4 address with good prefix
@Feature: IPAddr Generator
@Assert: A 4-group IPv4 address is generated
"""

result = gen_ipaddr(ip3=False, ipv6=False, prefix=[10])
self.assertTrue(
len(result.split(".")) == 4,
"Did not generate a 4-group IPv4 addrss")
self.assertTrue(result.startswith("10."))

def test_gen_ipv4_6(self):
"""
@Test: Generate a 4 group IPv4 address with good prefix
@Feature: IPAddr Generator
@Assert: A 4-group IPv4 address is generated
"""

result = gen_ipaddr(ip3=False, ipv6=False, prefix=[10, 10])
self.assertTrue(
len(result.split(".")) == 4,
"Did not generate a 4-group IPv4 addrss")
self.assertTrue(result.startswith("10.10."))

def test_gen_ipv4_7(self):
"""
@Test: Generate a 4 group IPv4 address with good prefix
@Feature: IPAddr Generator
@Assert: A 4-group IPv4 address is generated
"""

result = gen_ipaddr(ip3=False, ipv6=False, prefix=[10, 10, 10])
self.assertTrue(
len(result.split(".")) == 4,
"Did not generate a 4-group IPv4 addrss")
self.assertTrue(result.startswith("10.10.10."))

def test_gen_ipv4_8(self):
"""
@Test: Generate a 4 group IPv4 address with prefix disabling randomness
@Feature: IPAddr Generator
@Assert: An exception is raised
"""

with self.assertRaises(ValueError):
gen_ipaddr(ip3=False, ipv6=False, prefix=[10, 10, 10, 10])

def test_gen_ipv4_9(self):
"""
@Test: Generate a 4 group IPv4 address with prefix too long
@Feature: IPAddr Generator
@Assert: An exception is raised
"""

with self.assertRaises(ValueError):
gen_ipaddr(ip3=False, ipv6=False, prefix=[10, 10, 10, 10, 10])

def test_gen_ipv4_10(self):
"""
@Test: Generate a 3 group IPv4 address with good prefix
@Feature: IPAddr Generator
@Assert: A 3-group IPv4 address is generated
"""

result = gen_ipaddr(ip3=True, ipv6=False, prefix=[10, 10])
self.assertTrue(
len(result.split(".")) == 4,
"Did not generate a 4-group IPv4 addrss")
self.assertTrue(result.startswith("10.10."))
self.assertTrue(result.endswith(".0"))

def test_gen_ipv4_11(self):
"""
@Test: Generate a 3 group IPv4 address with prefix disabling randomness
@Feature: IPAddr Generator
@Assert: An exception is raised
"""

with self.assertRaises(ValueError):
gen_ipaddr(ip3=True, ipv6=False, prefix=[10, 10, 10])

def test_gen_ipv4_12(self):
"""
@Test: Generate a 3 group IPv4 address with prefix too long
@Feature: IPAddr Generator
@Assert: An exception is raised
"""

with self.assertRaises(ValueError):
gen_ipaddr(ip3=True, ipv6=False, prefix=[10, 10, 10, 10])

def test_gen_ipv6_1(self):
"""
@Test: Generate a IPv6 address
Expand All @@ -86,3 +179,52 @@ def test_gen_ipv6_2(self):
self.assertTrue(
len(result.split(":")) == 8,
"Did not generate a IPv6 addrss")

def test_gen_ipv6_3(self):
"""
@Test: Generate a IPv6 address with custom prefix
@Feature: IPAddr Generator
@Assert: A IPv6 address is generated
"""

result = gen_ipaddr(ipv6=True, prefix=["e2d3"])
self.assertTrue(
len(result.split(":")) == 8,
"Did not generate a IPv6 addrss")
self.assertTrue(result.startswith("e2d3:"))

def test_gen_ipv6_4(self):
"""
@Test: Generate a IPv6 address with custom (very long) prefix
@Feature: IPAddr Generator
@Assert: A IPv6 address is generated
"""

prefix = 7 * ["e2d3"]
result = gen_ipaddr(ipv6=True, prefix=prefix)
self.assertTrue(
len(result.split(":")) == 8,
"Did not generate a IPv6 addrss")
self.assertTrue(result.startswith(":".join(prefix)))

def test_gen_ipv6_5(self):
"""
@Test: Generate a IPv6 address with too long prefix
@Feature: IPAddr Generator
@Assert: ValueError raised
"""

prefix = 8 * ["e2d3"]
with self.assertRaises(ValueError):
gen_ipaddr(ipv6=True, prefix=prefix)

def test_gen_ipv6_6(self):
"""
@Test: Generate a IPv6 address with even longer prefix
@Feature: IPAddr Generator
@Assert: ValueError raised
"""

prefix = 9 * ["e2d3"]
with self.assertRaises(ValueError):
gen_ipaddr(ipv6=True, prefix=prefix)

0 comments on commit f2f62a4

Please sign in to comment.