Home | History | Annotate | Download | only in test
      1 #-*- coding: ISO-8859-1 -*-
      2 # pysqlite2/test/hooks.py: tests for various SQLite-specific hooks
      3 #
      4 # Copyright (C) 2006-2007 Gerhard Hring <gh (at] ghaering.de>
      5 #
      6 # This file is part of pysqlite.
      7 #
      8 # This software is provided 'as-is', without any express or implied
      9 # warranty.  In no event will the authors be held liable for any damages
     10 # arising from the use of this software.
     11 #
     12 # Permission is granted to anyone to use this software for any purpose,
     13 # including commercial applications, and to alter it and redistribute it
     14 # freely, subject to the following restrictions:
     15 #
     16 # 1. The origin of this software must not be misrepresented; you must not
     17 #    claim that you wrote the original software. If you use this software
     18 #    in a product, an acknowledgment in the product documentation would be
     19 #    appreciated but is not required.
     20 # 2. Altered source versions must be plainly marked as such, and must not be
     21 #    misrepresented as being the original software.
     22 # 3. This notice may not be removed or altered from any source distribution.
     23 
     24 import os, unittest
     25 import sqlite3 as sqlite
     26 
     27 class CollationTests(unittest.TestCase):
     28     def setUp(self):
     29         pass
     30 
     31     def tearDown(self):
     32         pass
     33 
     34     def CheckCreateCollationNotCallable(self):
     35         con = sqlite.connect(":memory:")
     36         try:
     37             con.create_collation("X", 42)
     38             self.fail("should have raised a TypeError")
     39         except TypeError, e:
     40             self.assertEqual(e.args[0], "parameter must be callable")
     41 
     42     def CheckCreateCollationNotAscii(self):
     43         con = sqlite.connect(":memory:")
     44         try:
     45             con.create_collation("coll", cmp)
     46             self.fail("should have raised a ProgrammingError")
     47         except sqlite.ProgrammingError, e:
     48             pass
     49 
     50     def CheckCollationIsUsed(self):
     51         if sqlite.version_info < (3, 2, 1):  # old SQLite versions crash on this test
     52             return
     53         def mycoll(x, y):
     54             # reverse order
     55             return -cmp(x, y)
     56 
     57         con = sqlite.connect(":memory:")
     58         con.create_collation("mycoll", mycoll)
     59         sql = """
     60             select x from (
     61             select 'a' as x
     62             union
     63             select 'b' as x
     64             union
     65             select 'c' as x
     66             ) order by x collate mycoll
     67             """
     68         result = con.execute(sql).fetchall()
     69         if result[0][0] != "c" or result[1][0] != "b" or result[2][0] != "a":
     70             self.fail("the expected order was not returned")
     71 
     72         con.create_collation("mycoll", None)
     73         try:
     74             result = con.execute(sql).fetchall()
     75             self.fail("should have raised an OperationalError")
     76         except sqlite.OperationalError, e:
     77             self.assertEqual(e.args[0].lower(), "no such collation sequence: mycoll")
     78 
     79     def CheckCollationReturnsLargeInteger(self):
     80         def mycoll(x, y):
     81             # reverse order
     82             return -((x > y) - (x < y)) * 2**32
     83         con = sqlite.connect(":memory:")
     84         con.create_collation("mycoll", mycoll)
     85         sql = """
     86             select x from (
     87             select 'a' as x
     88             union
     89             select 'b' as x
     90             union
     91             select 'c' as x
     92             ) order by x collate mycoll
     93             """
     94         result = con.execute(sql).fetchall()
     95         self.assertEqual(result, [('c',), ('b',), ('a',)],
     96                          msg="the expected order was not returned")
     97 
     98     def CheckCollationRegisterTwice(self):
     99         """
    100         Register two different collation functions under the same name.
    101         Verify that the last one is actually used.
    102         """
    103         con = sqlite.connect(":memory:")
    104         con.create_collation("mycoll", cmp)
    105         con.create_collation("mycoll", lambda x, y: -cmp(x, y))
    106         result = con.execute("""
    107             select x from (select 'a' as x union select 'b' as x) order by x collate mycoll
    108             """).fetchall()
    109         if result[0][0] != 'b' or result[1][0] != 'a':
    110             self.fail("wrong collation function is used")
    111 
    112     def CheckDeregisterCollation(self):
    113         """
    114         Register a collation, then deregister it. Make sure an error is raised if we try
    115         to use it.
    116         """
    117         con = sqlite.connect(":memory:")
    118         con.create_collation("mycoll", cmp)
    119         con.create_collation("mycoll", None)
    120         try:
    121             con.execute("select 'a' as x union select 'b' as x order by x collate mycoll")
    122             self.fail("should have raised an OperationalError")
    123         except sqlite.OperationalError, e:
    124             if not e.args[0].startswith("no such collation sequence"):
    125                 self.fail("wrong OperationalError raised")
    126 
    127 class ProgressTests(unittest.TestCase):
    128     def CheckProgressHandlerUsed(self):
    129         """
    130         Test that the progress handler is invoked once it is set.
    131         """
    132         con = sqlite.connect(":memory:")
    133         progress_calls = []
    134         def progress():
    135             progress_calls.append(None)
    136             return 0
    137         con.set_progress_handler(progress, 1)
    138         con.execute("""
    139             create table foo(a, b)
    140             """)
    141         self.assertTrue(progress_calls)
    142 
    143 
    144     def CheckOpcodeCount(self):
    145         """
    146         Test that the opcode argument is respected.
    147         """
    148         con = sqlite.connect(":memory:")
    149         progress_calls = []
    150         def progress():
    151             progress_calls.append(None)
    152             return 0
    153         con.set_progress_handler(progress, 1)
    154         curs = con.cursor()
    155         curs.execute("""
    156             create table foo (a, b)
    157             """)
    158         first_count = len(progress_calls)
    159         progress_calls = []
    160         con.set_progress_handler(progress, 2)
    161         curs.execute("""
    162             create table bar (a, b)
    163             """)
    164         second_count = len(progress_calls)
    165         self.assertTrue(first_count > second_count)
    166 
    167     def CheckCancelOperation(self):
    168         """
    169         Test that returning a non-zero value stops the operation in progress.
    170         """
    171         con = sqlite.connect(":memory:")
    172         progress_calls = []
    173         def progress():
    174             progress_calls.append(None)
    175             return 1
    176         con.set_progress_handler(progress, 1)
    177         curs = con.cursor()
    178         self.assertRaises(
    179             sqlite.OperationalError,
    180             curs.execute,
    181             "create table bar (a, b)")
    182 
    183     def CheckClearHandler(self):
    184         """
    185         Test that setting the progress handler to None clears the previously set handler.
    186         """
    187         con = sqlite.connect(":memory:")
    188         action = []
    189         def progress():
    190             action.append(1)
    191             return 0
    192         con.set_progress_handler(progress, 1)
    193         con.set_progress_handler(None, 1)
    194         con.execute("select 1 union select 2 union select 3").fetchall()
    195         self.assertEqual(len(action), 0, "progress handler was not cleared")
    196 
    197 def suite():
    198     collation_suite = unittest.makeSuite(CollationTests, "Check")
    199     progress_suite = unittest.makeSuite(ProgressTests, "Check")
    200     return unittest.TestSuite((collation_suite, progress_suite))
    201 
    202 def test():
    203     runner = unittest.TextTestRunner()
    204     runner.run(suite())
    205 
    206 if __name__ == "__main__":
    207     test()
    208