<commit_before>#!/usr/bin/python
"""Test suite for the database abstraction module (model)."""
__author__ = '<NAME> <<EMAIL>>'
__version__ = '1.0'

# Too many public methods
# pylint: disable=R0904

# Standard modules
import unittest

# Custom modules
from underdark.libs import app
from underdark.libs.sqltalk import mysql

# Unittest target
import model


# ##############################################################################
# Record classes for testing
#
class BasicTestRecord(model.Record):
  """Test record for offline tests."""


class Author(model.Record):
  """Author class for testing purposes."""


class Book(model.Record):
  """Book class for testing purposes."""


class Writer(model.Record):
  """Writer class for testing purposes, will manage `writers` table."""
  _TABLE = 'writers'


class VersionedAuthor(model.VersionedRecord):
  """Versioned author table for testing purposes."""


class VersionedBook(model.VersionedRecord):
  """Versioned Book class for testing purposes."""


# ##############################################################################
# Start of tests
#
class BaseRecordTests(unittest.TestCase):
  """Offline tests of methods and behavior of the BaseRecord class."""
  def setUp(self):
    """Sets up the tests for the offline Record test."""
    self.record_class = BasicTestRecord

  def testTableName(self):
    """[BaseRecord] TableName returns the expected value and obeys _TABLE"""
    self.assertEqual(self.record_class.TableName(), 'basicTestRecord')
    self.record_class._TABLE = 'WonderfulSpam'
    self.assertEqual(self.record_class.TableName(), 'WonderfulSpam')

  def testPrimaryKey(self):
    """[BaseRecord] Primary key value on `key` property, default field 'ID'"""
    record = self.record_class(None, {'ID': 12, 'name': '<NAME>'})
    self.assertEqual(record.key, 12)

  def testPrimaryKeyChanges(self):
    """[BaseRecord] Defining _PRIMARY_KEY overrides default value"""
    record = self.record_class(None, {'ID': 12, 'name': '<NAME>'})
    self.record_class._PRIMARY_KEY = 'name'
    self.assertEqual(record.key, '<NAME>')

  def testEquality(self):
    """[BaseRecord] Records of the same content are equal to eachother"""
    record_one = self.record_class(None, {'ID': 2, 'name': 'Rowling'})
    record_two = self.record_class(None, {'ID': 2, 'name': 'Rowling'})
    record_three = self.record_class(None, {'ID': 3, 'name': 'Rowling'})
    record_four = self.record_class(None, {'ID': 2, 'name': 'Rowling', 'x': 2})
    self.assertFalse(record_one is record_two)
    self.assertEqual(record_one, record_two)
    self.assertNotEqual(record_one, record_three)
    self.assertNotEqual(record_one, record_four)


class RecordTests(unittest.TestCase):
  """Online tests of methods and behavior of the Record class."""
  def setUp(self):
    """Sets up the tests for the Record class."""
    self.connection = DatabaseConnection()
    with self.connection as cursor:
      cursor.Execute("""CREATE TABLE `author` (
                            `ID` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
                            `name` varchar(32) NOT NULL,
                            PRIMARY KEY (`ID`)
                          ) ENGINE=InnoDB  DEFAULT CHARSET=utf8""")
      cursor.Execute("""CREATE TABLE `book` (
                            `ID` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
                            `author` smallint(5) unsigned NOT NULL,
                            `title` varchar(32) NOT NULL,
                            PRIMARY KEY (`ID`)
                          ) ENGINE=InnoDB DEFAULT CHARSET=utf8""")

  def tearDown(self):
    """Destroy tables after testing."""
    with self.connection as cursor:
      cursor.Execute('DROP TABLE `author`')
      cursor.Execute('DROP TABLE `book`')

  def testLoadPrimary(self):
    """[Record] Records can be loaded by primary key using FromPrimary()"""
    with self.connection as cursor:
      inserted = cursor.Insert(table='author', values={'name': '<NAME>'})
    author = Author.FromPrimary(self.connection, inserted.insertid)
    self.assertEqual(type(author), Author)
    self.assertEqual(len(author), 2)
    self.assertEqual(author.key, inserted.insertid)
    self.assertEqual(author['name'], '<NAME>')

  def testLoadPrimaryWithChangedKey(self):
    """[Record] Records can be loaded from alternative primary key"""
    with self.connection as cursor:
      inserted = cursor.Insert(table='author', values={'name': '<NAME>'})
    # Adjust primary key field name
    Author._PRIMARY_KEY = 'name'
    # Actual tests
    author = Author.FromPrimary(self.connection, '<NAME>')
    self.assertEqual(type(author), Author)
    self.assertEqual(len(author), 2)
    self.assertEqual(author.key, author['name'])
    self.assertEqual(author['ID'], inserted.insertid)
    # Restore global state
    Author._PRIMARY_KEY = 'ID'

  def testCreateRecord(self):
    """Database records can be created using Create()"""
    new_author = Author.Create(self.connection, {'name': '<NAME>'})
    author = Author.FromPrimary(self.connection, new_author.key)
    self.assertEqual(author['name'], '<NAME>')

  def testCreateRecordWithBadField(self):
    """Database record creation fails if there are unknown fields present"""
    self.assertRaises(model.BadFieldError, Author.Create, self.connection,
                      {'name': '<NAME>', 'email': '<EMAIL>'})

  def testLoadRelated(self):
    """Fieldnames that match tablenames trigger automatic loading"""
    Author.Create(self.connection, {'name': '<NAME>'})
    book = Book(self.connection, {'author': 1})
    self.assertEqual(type(book['author']), Author)
    self.assertEqual(book['author']['name'], '<NAME>')
    self.assertEqual(book['author'].key, 1)

  def testLoadRelatedFailure(self):
    """Automatic loading raises NotExistError if the foreign record is absent"""
    book = Book(self.connection, {'author': 1})
    self.assertRaises(model.NotExistError, book.__getitem__, 'author')

  def testLoadRelatedSuppressedForNone(self):
    """Automatic loading is not attempted when the field value is `None`"""
    book = Book(self.connection, {'author': None})
    self.assertEqual(book['author'], None)

  def testUpdateRecord(self):
    """The record can be given new values and these are properly stored"""
    author = Author.Create(self.connection, {'name': '<NAME>'})
    author['name'] = '<NAME>'
    author.Save()
    same_author = Author.FromPrimary(self.connection, 1)
    self.assertEqual(same_author['name'], '<NAME>')
    self.assertEqual(same_author, author)

  def testUpdateRecordWithBadField(self):
    """Database record updating fails if there are unknown fields present"""
    author = Author.Create(self.connection, {'name': '<NAME>'})
    author['specialty'] = 'poetry'
    self.assertRaises(model.BadFieldError, author.Save)

  def testUpdatePrimaryKey(self):
    """Saving with an updated primary key properly saved the record"""
    author = Author.Create(self.connection, {'name': '<NAME>'})
    self.assertEqual(author.key, 1)
    author['ID'] = 101
    author.Save()
    self.assertRaises(model.NotExistError, Author.FromPrimary,
                      self.connection, 1)
    same_author = Author.FromPrimary(self.connection, 101)
    self.assertEqual(same_author, author)


class NonStandardTableAndRelations(unittest.TestCase):
  """Verified autoloading works for records with an alternate table name."""
  def setUp(self):
    """Sets up the tests for the Record class."""
    self.connection = DatabaseConnection()
    with self.connection as cursor:
      cursor.Execute("""CREATE TABLE `writers` (<commit_msg>changed test method order to make the progression more logical.<commit_after>#!/usr/bin/python
"""Test suite for the database abstraction module (model)."""
__author__ = '<NAME> <<EMAIL>>'
__version__ = '1.0'

# Too many public methods
# pylint: disable=R0904

# Standard modules
import unittest

# Custom modules
from underdark.libs import app
from underdark.libs.sqltalk import mysql

# Unittest target
import model


# ##############################################################################
# Record classes for testing
#
class BasicTestRecord(model.Record):
  """Test record for offline tests."""


class Author(model.Record):
  """Author class for testing purposes."""


class Book(model.Record):
  """Book class for testing purposes."""


class Writer(model.Record):
  """Writer class for testing purposes, will manage `writers` table."""
  _TABLE = 'writers'


class VersionedAuthor(model.VersionedRecord):
  """Versioned author table for testing purposes."""


class VersionedBook(model.VersionedRecord):
  """Versioned Book class for testing purposes."""


# ##############################################################################
# Start of tests
#
class BaseRecordTests(unittest.TestCase):
  """Offline tests of methods and behavior of the BaseRecord class."""
  def setUp(self):
    """Sets up the tests for the offline Record test."""
    self.record_class = BasicTestRecord

  def testTableName(self):
    """[BaseRecord] TableName returns the expected value and obeys _TABLE"""
    self.assertEqual(self.record_class.TableName(), 'basicTestRecord')
    self.record_class._TABLE = 'WonderfulSpam'
    self.assertEqual(self.record_class.TableName(), 'WonderfulSpam')

  def testPrimaryKey(self):
    """[BaseRecord] Primary key value on `key` property, default field 'ID'"""
    record = self.record_class(None, {'ID': 12, 'name': '<NAME>'})
    self.assertEqual(record.key, 12)

  def testPrimaryKeyChanges(self):
    """[BaseRecord] Defining _PRIMARY_KEY overrides default value"""
    record = self.record_class(None, {'ID': 12, 'name': '<NAME>'})
    self.record_class._PRIMARY_KEY = 'name'
    self.assertEqual(record.key, 'K. May')

  def testEquality(self):
    """[BaseRecord] Records of the same content are equal to eachother"""
    record_one = self.record_class(None, {'ID': 2, 'name': 'Rowling'})
    record_two = self.record_class(None, {'ID': 2, 'name': 'Rowling'})
    record_three = self.record_class(None, {'ID': 3, 'name': 'Rowling'})
    record_four = self.record_class(None, {'ID': 2, 'name': 'Rowling', 'x': 2})
    self.assertFalse(record_one is record_two)
    self.assertEqual(record_one, record_two)
    self.assertNotEqual(record_one, record_three)
    self.assertNotEqual(record_one, record_four)


class RecordTests(unittest.TestCase):
  """Online tests of methods and behavior of the Record class."""
  def setUp(self):
    """Sets up the tests for the Record class."""
    self.connection = DatabaseConnection()
    with self.connection as cursor:
      cursor.Execute("""CREATE TABLE `author` (
                            `ID` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
                            `name` varchar(32) NOT NULL,
                            PRIMARY KEY (`ID`)
                          ) ENGINE=InnoDB  DEFAULT CHARSET=utf8""")
      cursor.Execute("""CREATE TABLE `book` (
                            `ID` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
                            `author` smallint(5) unsigned NOT NULL,
                            `title` varchar(32) NOT NULL,
                            PRIMARY KEY (`ID`)
                          ) ENGINE=InnoDB DEFAULT CHARSET=utf8""")

  def tearDown(self):
    """Destroy tables after testing."""
    with self.connection as cursor:
      cursor.Execute('DROP TABLE `author`')
      cursor.Execute('DROP TABLE `book`')

  def testLoadPrimary(self):
    """[Record] Records can be loaded by primary key using FromPrimary()"""
    with self.connection as cursor:
      inserted = cursor.Insert(table='author', values={'name': '<NAME>'})
    author = Author.FromPrimary(self.connection, inserted.insertid)
    self.assertEqual(type(author), Author)
    self.assertEqual(len(author), 2)
    self.assertEqual(author.key, inserted.insertid)
    self.assertEqual(author['name'], '<NAME>')

  def testLoadPrimaryWithChangedKey(self):
    """[Record] Records can be loaded from alternative primary key"""
    with self.connection as cursor:
      inserted = cursor.Insert(table='author', values={'name': '<NAME>'})
    # Adjust primary key field name
    Author._PRIMARY_KEY = 'name'
    # Actual tests
    author = Author.FromPrimary(self.connection, '<NAME>')
    self.assertEqual(type(author), Author)
    self.assertEqual(len(author), 2)
    self.assertEqual(author.key, author['name'])
    self.assertEqual(author['ID'], inserted.insertid)
    # Restore global state
    Author._PRIMARY_KEY = 'ID'

  def testCreateRecord(self):
    """Database records can be created using Create()"""
    new_author = Author.Create(self.connection, {'name': '<NAME>'})
    author = Author.FromPrimary(self.connection, new_author.key)
    self.assertEqual(author['name'], '<NAME>')

  def testCreateRecordWithBadField(self):
    """Database record creation fails if there are unknown fields present"""
    self.assertRaises(model.BadFieldError, Author.Create, self.connection,
                      {'name': '<NAME>', 'email': '<EMAIL>'})

  def testUpdateRecord(self):
    """The record can be given new values and these are properly stored"""
    author = Author.Create(self.connection, {'name': '<NAME>'})
    author['name'] = '<NAME>'
    author.Save()
    same_author = Author.FromPrimary(self.connection, 1)
    self.assertEqual(same_author['name'], '<NAME>')
    self.assertEqual(same_author, author)

  def testUpdateRecordWithBadField(self):
    """Database record updating fails if there are unknown fields present"""
    author = Author.Create(self.connection, {'name': '<NAME>'})
    author['specialty'] = 'poetry'
    self.assertRaises(model.BadFieldError, author.Save)

  def testUpdatePrimaryKey(self):
    """Saving with an updated primary key properly saved the record"""
    author = Author.Create(self.connection, {'name': '<NAME>'})
    self.assertEqual(author.key, 1)
    author['ID'] = 101
    author.Save()
    self.assertRaises(model.NotExistError, Author.FromPrimary,
                      self.connection, 1)
    same_author = Author.FromPrimary(self.connection, 101)
    self.assertEqual(same_author, author)

  def testLoadRelated(self):
    """Fieldnames that match tablenames trigger automatic loading"""
    Author.Create(self.connection, {'name': '<NAME>'})
    book = Book(self.connection, {'author': 1})
    self.assertEqual(type(book['author']), Author)
    self.assertEqual(book['author']['name'], '<NAME>')
    self.assertEqual(book['author'].key, 1)

  def testLoadRelatedFailure(self):
    """Automatic loading raises NotExistError if the foreign record is absent"""
    book = Book(self.connection, {'author': 1})
    self.assertRaises(model.NotExistError, book.__getitem__, 'author')

  def testLoadRelatedSuppressedForNone(self):
    """Automatic loading is not attempted when the field value is `None`"""
    book = Book(self.connection, {'author': None})
    self.assertEqual(book['author'], None)


class NonStandardTableAndRelations(unittest.TestCase):
  """Verified autoloading works for records with an alternate table name."""
  def setUp(self):
    """Sets up the tests for the Record class."""
    self.connection = DatabaseConnection()
    with self.connection as cursor:
      cursor.Execute("""CREATE TABLE `writers` (
{'fraction_non_alphanumeric': 0.15242072295445647, 'fraction_numerical': 0.0052198877724128935, 'mean_word_length': 3.923546418246065, 'pattern_counts': {'":': 0, '<': 44, '<?xml version=': 0, '>': 44, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1945211', 'n_tokens_mistral': 4400, 'n_tokens_neox': 4229, 'n_words': 1190}