def test_one_of_type_generator(self):
    # options
    data = fake(schema.one_of(schema.boolean, schema.number(1), schema.number(0)))
    self.assertIn(data, (True, False, 1, 0))

    # overriding
    data = fake(schema.one_of(schema.string('true'), schema.string('false')), 'true')
    self.assertEqual(data, 'true')
  def test_it_validates_keys(self):
    self.assertValidationPasses({}, schema.object({}))

    self.assertValidationPasses(
      {
        'string': 'banana',
        'number': 42,
        'array': [0, 1],
        'empty_object': {},
        'object': {
          'boolean': True,
          'object': {
            'nothing': None
          }
        }
      },
      schema.object({
        'string':       schema.string('banana'),
        'number':       schema.number(42),
        'array':        schema.array([schema.number(0), schema.number(1)]),
        'empty_object': schema.object({}),
        'object':       schema.object({
                          'boolean': schema.boolean(True),
                          'object': schema.object({
                            'nothing': schema.null
                          })
                        })
      })
    )

    self.assertValidationFails(None,        schema.object({}))
    self.assertValidationFails({},          schema.object({'id': schema.integer}))
    self.assertValidationFails({'id': '1'}, schema.object({'id': schema.integer}))
  def test_array_of_type_generator(self):
    # type
    data = fake(schema.array_of(schema.integer))
    self.assertIsInstance(data, list)
    self.assertTrue(all(isinstance(x, int) for x in data))

    # overriding
    data = fake(schema.array_of(schema.integer), 0)
    self.assertEqual(data, 0)

    # example
    example = ['banana', 'cucumber']
    data = fake(schema.array_of(schema.string).example(example))
    self.assertEqual(data, example)

    # items_schema
    data = fake(schema.array_of(schema.string('banana')))
    self.assertTrue(all(x == 'banana' for x in data))

    # unique
    data = fake(schema.array_of(schema.integer.between(0, 1)).length(2).unique)
    self.assertEqual([0, 1], sorted(data))
    
    # length
    data = fake(schema.array_of(schema.array).length(5))
    self.assertEqual(len(data), 5)

    data = fake(schema.array_of(schema.array).length(0, 2))
    self.assertTrue(0 <= len(data) <= 2)

    data = fake(schema.array_of(schema.string).min_length(1))
    self.assertGreaterEqual(len(data), 1)

    data = fake(schema.array_of(schema.string).max_length(1))
    self.assertLessEqual(len(data), 1)
  def test_it_validates_nullable(self):
    self.assertValidationPasses(None, schema.string.nullable)
    self.assertValidationPasses(None, schema.string('banana').nullable)

    self.assertValidationFails(False, schema.string.nullable)
    self.assertValidationFails(0,     schema.string.nullable)
    self.assertValidationFails([],    schema.string.nullable)
    self.assertValidationFails({},    schema.string.nullable)
    def test_it_validates_items(self):
        self.assertValidationPasses([], schema.array([]))
        self.assertValidationPasses([42], schema.array([schema.integer(42)]))
        self.assertValidationPasses([0, 1], schema.array([schema.integer(0), schema.integer(1)]))

        self.assertValidationFails([], schema.array([schema.integer(42)]))
        self.assertValidationFails([42], schema.array([]))
        self.assertValidationFails(42, schema.array([schema.integer(42)]))
        self.assertValidationFails(["42"], schema.array([schema.integer(42)]))

        self.assertValidationFails(
            ["banana", "cucumber", "carrot"], schema.array([schema.string("banana"), schema.string("cucumber")])
        )

        self.assertValidationFails(
            ["banana", "cucumber"],
            schema.array([schema.string("banana"), schema.string("cucumber"), schema.string("carrot")]),
        )
  def test_it_validates_value(self):
    self.assertValidationPasses('banana', schema.string('banana'))
    self.assertValidationPasses('',       schema.string(''))
    self.assertValidationPasses(' ',      schema.string(' '))

    self.assertValidationFails(None,     schema.string(''))
    self.assertValidationFails('banana', schema.string('cucumber'))
    self.assertValidationFails('',       schema.string(' '))
    self.assertValidationFails(' ',      schema.string(''))
    def test_it_validates_value(self):
        self.assertValidationPasses('banana', schema.string('banana'))
        self.assertValidationPasses('', schema.string(''))
        self.assertValidationPasses(' ', schema.string(' '))

        self.assertValidationFails(None, schema.string(''))
        self.assertValidationFails('banana', schema.string('cucumber'))
        self.assertValidationFails('', schema.string(' '))
        self.assertValidationFails(' ', schema.string(''))
    def test_it_validates_nullable(self):
        with warnings.catch_warnings():
            warnings.simplefilter('ignore')

            self.assertValidationPasses(None, schema.string.nullable)
            self.assertValidationPasses(None, schema.string('banana').nullable)

            self.assertValidationFails(False, schema.string.nullable)
            self.assertValidationFails(0, schema.string.nullable)
            self.assertValidationFails([], schema.string.nullable)
            self.assertValidationFails({}, schema.string.nullable)
  def test_it_validates_optional_keys(self):
    self.assertValidationPasses(
      {
        'id': 1234
      },
      schema.object({
        'id':     schema.integer(1234),
        'title?': schema.string('banana')
      })
    )

    self.assertValidationFails(
      {
        'id': 1234,
        'title': 'not banana'
      },
      schema.object({
        'id':     schema.integer(1234),
        'title?': schema.string('banana')
      })
    )
    def test_it_validates_items(self):
        self.assertValidationPasses([], schema.array([]))
        self.assertValidationPasses([42], schema.array([schema.integer(42)]))
        self.assertValidationPasses([0, 1],
                                    schema.array(
                                        [schema.integer(0),
                                         schema.integer(1)]))

        self.assertValidationFails([], schema.array([schema.integer(42)]))
        self.assertValidationFails([42], schema.array([]))
        self.assertValidationFails(42, schema.array([schema.integer(42)]))
        self.assertValidationFails(['42'], schema.array([schema.integer(42)]))

        self.assertValidationFails(
            ['banana', 'cucumber', 'carrot'],
            schema.array([schema.string('banana'),
                          schema.string('cucumber')]))

        self.assertValidationFails(['banana', 'cucumber'],
                                   schema.array([
                                       schema.string('banana'),
                                       schema.string('cucumber'),
                                       schema.string('carrot')
                                   ]))
 def test_string_type_representation(self):
   self.assertRepr(schema.string,                      'schema.string')
   self.assertRepr(schema.string('banana'),            "schema.string('banana')")
   self.assertRepr(schema.string.length(32),           'schema.string.length(32)')
   self.assertRepr(schema.string.length(1, 64),        'schema.string.length(1, 64)')
   self.assertRepr(schema.string.min_length(1),        'schema.string.min_length(1)')
   self.assertRepr(schema.string.max_length(128),      'schema.string.max_length(128)')
   self.assertRepr(schema.string.empty,                'schema.string.empty')
   self.assertRepr(schema.string.non_empty,            'schema.string.non_empty')
   self.assertRepr(schema.string.pattern(r'[0-9\-_]'), "schema.string.pattern(r'[0-9\-_]')")
   self.assertRepr(schema.string.uri,                  'schema.string.uri')
   self.assertRepr(schema.string.alphabetic,           'schema.string.alphabetic')
   self.assertRepr(schema.string.numeric,              'schema.string.numeric')
   self.assertRepr(schema.string.alpha_num,            'schema.string.alpha_num')
   self.assertRepr(schema.string.lowercase,            'schema.string.lowercase')
   self.assertRepr(schema.string.uppercase,            'schema.string.uppercase')
   self.assertRepr(schema.string.nullable,             'schema.string.nullable')
  def test_array_type_representation(self):
    self.assertRepr(schema.array,                'schema.array')
    self.assertRepr(schema.array.nullable,       'schema.array.nullable')
    self.assertRepr(schema.array([]),            'schema.array([])')
    self.assertRepr(schema.array.length(10),     'schema.array.length(10)')
    self.assertRepr(schema.array.length(1, 2),   'schema.array.length(1, 2)')
    self.assertRepr(schema.array.min_length(1),  'schema.array.min_length(1)')
    self.assertRepr(schema.array.max_length(10), 'schema.array.max_length(10)')
    self.assertRepr(schema.array.empty,          'schema.array.empty')
    self.assertRepr(schema.array.non_empty,      'schema.array.non_empty')
    
    self.assertRepr(schema.array.unique,
                   'schema.array.unique')
    self.assertRepr(schema.array.unique(lambda a, b: a != b),
                   'schema.array.unique(<predicate>)')

    self.assertRepr(schema.array([schema.integer(0), schema.integer(1)]),
                   'schema.array([schema.integer(0), schema.integer(1)])')

    self.assertRepr(schema.array.contains(schema.integer(42)),
                   'schema.array.contains(schema.integer(42))')
    self.assertRepr(schema.array.contains_one(schema.boolean),
                   'schema.array.contains_one(schema.boolean)')
    self.assertRepr(schema.array.contains_many(schema.string('banana')),
                   "schema.array.contains_many(schema.string('banana'))")

    self.assertRepr(
      schema.array.contains(schema.object({
        'id': schema.integer(1)
      })),
      "schema.array.contains(schema.object({" + "\n" +
      "  'id': schema.integer(1)" + "\n" +
      "}))"
    )

    self.assertRepr(
      schema.array([
        schema.integer(1),
        schema.integer(2),
        schema.integer(3)
      ]),
      "schema.array([" + "\n" +
      "  schema.integer(1)," + "\n" +
      "  schema.integer(2)," + "\n" +
      "  schema.integer(3)" + "\n" +
      "])"
    )
    
    self.assertRepr(
      schema.array([
        schema.integer(1),
        schema.integer(2),
        schema.object({
          'id': schema.string.numeric
        })
      ]),
      "schema.array([" + "\n" +
      "  schema.integer(1)," + "\n" +
      "  schema.integer(2)," + "\n" +
      "  schema.object({" + "\n" +
      "    'id': schema.string.numeric" + "\n" +
      "  })" + "\n" +
      "])"
    )

    self.assertRepr(
      schema.object({
        'items': schema.array([schema.object({
          'id': schema.string.numeric
        })])
      }),
      "schema.object({" + "\n" +
      "  'items': schema.array([schema.object({" + "\n" +
      "    'id': schema.string.numeric" + "\n" +
      "  })])" + "\n" +
      "})"
    )
  def test_string_type_generator(self):
    import string

    # type
    data = fake(schema.string)
    self.assertIsInstance(data, str)
    self.assertGreaterEqual(len(data), 0)
    self.assertTrue(all(x in string.printable for x in data))

    # value
    data = fake(schema.string('banana'))
    self.assertEqual(data, 'banana')

    # overriding
    data = fake(schema.string('cucumber'), 'banana')
    self.assertEqual(data, 'banana')

    # example
    data = fake(schema.string.example(''))
    self.assertEqual(data, '')

    # pattern
    regex = r'[abc]+'
    data = fake(schema.string.pattern(regex))
    self.assertRegex(data, regex)
    
    # numeric
    data = fake(schema.string.numeric)
    self.assertIsInstance(data, str)
    self.assertRegex(data, r'^[0-9]*$')
    
    # alphabetic
    data = fake(schema.string.alphabetic)
    self.assertRegex(data, r'^[a-zA-Z]*$')

    # alphabetic length
    data = fake(schema.string.alphabetic.length(10))
    self.assertEqual(len(data), 10)

    # alphabetic lowercase
    data = fake(schema.string.alphabetic.lowercase)
    self.assertRegex(data, r'^[a-z]*$')

    # alphabetic lowercase length
    data = fake(schema.string.alphabetic.lowercase.length(10))
    self.assertEqual(len(data), 10)

    # alphabetic uppercase
    data = fake(schema.string.alphabetic.uppercase)
    self.assertRegex(data, r'^[A-Z]*$')

    # alphabetic uppercase length
    data = fake(schema.string.alphabetic.uppercase.length(10))
    self.assertEqual(len(data), 10)

    # alpha_num
    data = fake(schema.string.alpha_num)
    self.assertRegex(data, r'^[a-zA-Z0-9]*$')

    # alpha_num length
    data = fake(schema.string.alpha_num.length(10))
    self.assertEqual(len(data), 10)

    # alpha_num lowercase
    data = fake(schema.string.alpha_num.lowercase)
    self.assertRegex(data, r'^[a-z0-9]*$')

    # alpha_num lowercase length
    data = fake(schema.string.alpha_num.lowercase.length(10))
    self.assertEqual(len(data), 10)

    # alpha_num uppercase
    data = fake(schema.string.alpha_num.uppercase)
    self.assertRegex(data, r'^[A-Z0-9]*$')

    # alpha_num uppercase length
    data = fake(schema.string.alpha_num.uppercase.length(10))
    self.assertEqual(len(data), 10)

    # length
    data = fake(schema.string.length(0))
    self.assertEqual(len(data), 0)

    data = fake(schema.string.length(1))
    self.assertEqual(len(data), 1)

    data = fake(schema.string.length(1, 2))
    self.assertTrue(1 <= len(data) <= 2)

    data = fake(schema.string.min_length(1))
    self.assertGreaterEqual(len(data), 1)

    data = fake(schema.string.max_length(1))
    self.assertLessEqual(len(data), 1)

    # empty
    data = fake(schema.string.empty)
    self.assertEqual(data, '')

    data = fake(schema.string.non_empty)
    self.assertGreaterEqual(len(data), 1)
  def test_array_type_generator(self):
    # type
    data = fake(schema.array)
    self.assertIsInstance(data, list)
    self.assertTrue(all(type(x) in self.primitive_types for x in data))

    # overriding
    array = [0, 1]
    data = fake(schema.array([schema.integer, schema.integer]), array)
    self.assertEqual(data, array)

    # example
    examples = (['true', 'false'], ['false', 'true'])
    data = fake(schema.array.examples(*examples))
    self.assertIn(data, examples)

    # items
    data = fake(schema.array([schema.number(0), schema.number(1)]))
    self.assertEqual(data, [0, 1])

    # contains
    data = fake(schema.array.contains(schema.integer(42)))
    self.assertGreaterEqual(data.count(42), 1)

    data = fake(schema.array.contains(schema.string('banana')).length(1))
    self.assertEqual(data, ['banana'])

    # contains_one
    data = fake(schema.array.contains_one(schema.integer(42)))
    self.assertIn(42, data)

    data = fake(schema.array.contains_one(schema.string('banana')).length(1))
    self.assertEqual(data, ['banana'])
    
    # contains_many
    data = fake(schema.array.contains_many(schema.integer(42)))
    self.assertGreaterEqual(data.count(42), 2)

    data = fake(schema.array.contains_many(schema.string('banana')).length(2))
    self.assertEqual(data, ['banana', 'banana'])

    # unique
    data = fake(schema.array([schema.boolean, schema.boolean]).unique)
    self.assertIn(True, data)
    self.assertIn(False, data)

    data = fake(schema.array.unique)
    self.assertEqual(len(set(data)), len(data))

    # length
    data = fake(schema.array.length(1))
    self.assertEqual(len(data), 1)

    data = fake(schema.array.length(1, 2))
    self.assertTrue(1 <= len(data) <= 2)

    data = fake(schema.array.min_length(1))
    self.assertGreaterEqual(len(data), 1)

    data = fake(schema.array.max_length(1))
    self.assertLessEqual(len(data), 1)

    # empty
    data = fake(schema.array.empty)
    self.assertEqual(data, [])

    data = fake(schema.array.non_empty)
    self.assertGreaterEqual(len(data), 1)