Module: Flores::Random

Defined in:
lib/flores/random.rb

Overview

A collection of methods intended for use in randomized testing.

Constant Summary collapse

CHARACTERS =

A selection of UTF-8 characters

I’d love to generate this, but I don’t yet know enough about how unicode blocks are allocated to do that. For now, hardcode a set of possible characters.

[
  # Basic Latin
  *(32..126).map(&:chr).map { |c| c.force_encoding(Encoding.default_external) },

  # hand-selected CJK Unified Ideographs Extension A
  "㐤", "㐨", "㐻", "㑐",

  # hand-selected Hebrew
  "א", "ב", "ג", "ד", "ה",

  # hand-selected Cyrillic
  "Є", "Б", "Р", "н", "я"
]

Class Method Summary collapse

Class Method Details

.characterString

Generates a random character (A string of length 1)

Returns:

  • (String)


57
58
59
# File 'lib/flores/random.rb', line 57

def self.character
  return CHARACTERS[integer(0...CHARACTERS.length)]
end

.integer(range) ⇒ Object

Return a random integer value within a given range.

Parameters:

  • range (Range)

Raises:

  • (ArgumentError)


64
65
66
67
# File 'lib/flores/random.rb', line 64

def self.integer(range)
  raise ArgumentError, "Range not given, got #{range.class}: #{range.inspect}" if !range.is_a?(Range)
  rand(range)
end

.ipv4Object

Return a random IPv4 address as a string



98
99
100
101
102
# File 'lib/flores/random.rb', line 98

def self.ipv4
  # TODO(sissel): Support CIDR range restriction?
  # TODO(sissel): Support netmask restriction?
  [integer(0..IPV4_MAX)].pack("N").unpack("C4").join(".")
end

.ipv6Object

Return a random IPv6 address as a string

The address may be in abbreviated form (ABCD::01EF):w



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/flores/random.rb', line 107

def self.ipv6
  # TODO(sissel): Support CIDR range restriction?
  # TODO(sissel): Support netmask restriction?
  length = integer(2..8)
  if length == 8
    # Full address; nothing to abbreviate
    ipv6_pack(length)
  else
    abbreviation = ipv6_abbreviation(length)
    if length == 2
      first = 1
      second = 1
    else
      first = integer(2...length)
      second = length - first
    end
    ipv6_pack(first) + abbreviation + ipv6_pack(second)
  end
end

.item(array) ⇒ Object

Return a random element from an array



93
94
95
# File 'lib/flores/random.rb', line 93

def self.item(array)
  array[integer(0...array.size)]
end

.iterations(range, &block) ⇒ Object

Run a block a random number of times.

Parameters:

  • range (Fixnum of Range)

    same meaning as #integer(range)



82
83
84
85
86
87
88
89
90
# File 'lib/flores/random.rb', line 82

def self.iterations(range, &block)
  range = 0..range if range.is_a?(Numeric)
  if block_given?
    integer(range).times(&block)
    nil
  else
    integer(range).times
  end
end

.number(range) ⇒ Object

Return a random number within a given range.

Parameters:

  • range (Range)

Raises:

  • (ArgumentError)


72
73
74
75
76
77
# File 'lib/flores/random.rb', line 72

def self.number(range)
  raise ArgumentError, "Range not given, got #{range.class}: #{range.inspect}" if !range.is_a?(Range)
  # Ruby 1.9.3 and below do not have Enumerable#size, so we have to compute the size of the range
  # ourselves.
  rand * (range.end - range.begin) + range.begin
end

.tcp_listener(host = "127.0.0.1") ⇒ Object

Get a TCP socket bound and listening on a random port.

You are responsible for closing the socket.

Returns [socket, address, port]



132
133
134
# File 'lib/flores/random.rb', line 132

def self.tcp_listener(host = "127.0.0.1")
  socket_listener(Socket::SOCK_STREAM, host)
end

.text(length) ⇒ String

Generates text with random characters of a given length (or within a length range)

  • The length can be a number or a range x..y. If a range, it must be ascending (x < y)

  • Negative lengths are not permitted and will raise an ArgumentError

Parameters:

  • length (Fixnum or Range)

    the length of text to generate

Returns:

  • (String)

    the generated text

Raises:

  • (ArgumentError)


37
38
39
40
41
42
# File 'lib/flores/random.rb', line 37

def self.text(length)
  return text_range(length) if length.is_a?(Range)

  raise ArgumentError, "A negative length is not permitted, I received #{length}" if length < 0
  length.times.collect { character }.join
end

.text_range(range) ⇒ String

Generate text with random characters of a length within the given range.

Parameters:

  • range (Range)

    the range of length to generate, inclusive

Returns:

  • (String)

    the generated text

Raises:

  • (ArgumentError)


48
49
50
51
52
# File 'lib/flores/random.rb', line 48

def self.text_range(range)
  raise ArgumentError, "Requires ascending range, you gave #{range}." if range.end < range.begin
  raise ArgumentError, "A negative range values are not permitted, I received range #{range}" if range.begin < 0
  text(integer(range))
end

.udp_listener(host = "127.0.0.1") ⇒ Object

Get a UDP socket bound and listening on a random port.

You are responsible for closing the socket.

Returns [socket, address, port]



141
142
143
# File 'lib/flores/random.rb', line 141

def self.udp_listener(host = "127.0.0.1")
  socket_listener(Socket::SOCK_DGRAM, host)
end