|
@@ -0,0 +1,175 @@
|
|
1
|
+import os
|
|
2
|
+import logging
|
|
3
|
+import random
|
|
4
|
+
|
|
5
|
+from unittest import TestCase
|
|
6
|
+import unittest
|
|
7
|
+
|
|
8
|
+from Database.sqlwrapper import SqlWrapper
|
|
9
|
+
|
|
10
|
+from django.conf import settings
|
|
11
|
+from Database.sqlsettings import SQLSettings
|
|
12
|
+
|
|
13
|
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Lodel.settings")
|
|
14
|
+
|
|
15
|
+#Bad strings for injection tests
|
|
16
|
+INJECTIONS = [ 'foo UNION SELECT 1,2,3,4--', "foo' UNION SELECT 1,2,3--", 'foo" UNION SELECT 1,2,3--', 'foo` UNION SELECT 1,2,3,4--', '--', 'foo`; SELECT 1,2,3', 'foo"; SELECT 1,2,3', "foo'; SELECT 1,2,3", "; SELECT 1,2,3" ]
|
|
17
|
+NAMEINJECT = INJECTIONS + [ '%', '*', "\0", "\b\b\b\b\b\b\b\b\b" ]
|
|
18
|
+
|
|
19
|
+#Valid SQL types
|
|
20
|
+VTYPES = [ 'integer', 'varchar(1)', 'varchar(50)', 'text', 'boolean' ]
|
|
21
|
+
|
|
22
|
+class SqlWrapperQueryStrTests(TestCase):
|
|
23
|
+
|
|
24
|
+ def setUp(self):
|
|
25
|
+ #creating a test table
|
|
26
|
+ sw = SqlWrapper()
|
|
27
|
+ self.ttn = 'testtable'
|
|
28
|
+ self.cols = [
|
|
29
|
+ { 'name': 'pk', 'type': 'INTEGER', 'extra': {'primarykey': True} },
|
|
30
|
+ { 'name': 'testtxt', 'type': 'TEXT', 'extra': {'nullable': True, 'default': 'hello'} },
|
|
31
|
+ { 'name': 'testchr', 'type': 'VARCHAR(50)', 'extra': {'nullable': True, 'default': 'hello world'} },
|
|
32
|
+ { 'name': 'testbool', 'type': 'BOOLEAN', 'extra': {'nullable':False, 'default': False}},
|
|
33
|
+ ]
|
|
34
|
+
|
|
35
|
+ sw.create_table( { 'name': self.ttn, 'columns': self.cols} )
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+ #Disable logging but CRITICAL
|
|
39
|
+ logging.basicConfig(level=logging.CRITICAL)
|
|
40
|
+ pass
|
|
41
|
+
|
|
42
|
+ def tearDown(self):
|
|
43
|
+ sw = SqlWrapper()
|
|
44
|
+ sw.drop_table(self.ttn)
|
|
45
|
+
|
|
46
|
+ @unittest.skip('dev') #TODO remove skip
|
|
47
|
+ def test_get_querystring(self):
|
|
48
|
+ sw = SqlWrapper()
|
|
49
|
+
|
|
50
|
+ actions = [ 'add_column', 'alter_column', 'drop_column' ]
|
|
51
|
+ dialects = [ 'default', 'mysql', 'postgresql' ]
|
|
52
|
+
|
|
53
|
+ for action in actions:
|
|
54
|
+ for dialect in dialects:
|
|
55
|
+ r = sw.get_querystring(action, dialect)
|
|
56
|
+ self.assertIsInstance(r, str)
|
|
57
|
+
|
|
58
|
+ @unittest.skip('dev') #TODO remove skip
|
|
59
|
+ def test_get_querystring_badargs(self):
|
|
60
|
+ sw = SqlWrapper()
|
|
61
|
+
|
|
62
|
+ actions = [ 1, -1, print, [], 'foo']
|
|
63
|
+ dialects = actions
|
|
64
|
+ for action in actions:
|
|
65
|
+ for dialect in dialects:
|
|
66
|
+ with self.assertRaises(ValueError):
|
|
67
|
+ r = sw.get_querystring(action, dialect)
|
|
68
|
+
|
|
69
|
+ @unittest.skip('dev') #TODO remove skip
|
|
70
|
+ def test_add_column(self):
|
|
71
|
+ sw = SqlWrapper()
|
|
72
|
+
|
|
73
|
+ colnames = [ 'taddcol1', 'test-add-col', 'test_add_col', '-test', '_add', '__col__' ]
|
|
74
|
+
|
|
75
|
+ for i, name in enumerate(colnames):
|
|
76
|
+ col = { 'name': name, 'type': VTYPES[i%len(VTYPES)] }
|
|
77
|
+ self.assertTrue(sw.add_column(self.ttn, col))
|
|
78
|
+ pass
|
|
79
|
+
|
|
80
|
+ @unittest.skip('dev') #TODO remove skip
|
|
81
|
+ def test_add_column_badargs(self):
|
|
82
|
+ sw = SqlWrapper()
|
|
83
|
+
|
|
84
|
+ coolname = 'cool'
|
|
85
|
+ i=0
|
|
86
|
+ self.assertFalse(sw.add_column(self.ttn, {'type': 'INTEGER'}))
|
|
87
|
+ self.assertFalse(sw.add_column(self.ttn, {'name': 'foo'}))
|
|
88
|
+ self.assertFalse(sw.add_column(self.ttn, dict()))
|
|
89
|
+ self.assertFalse(sw.add_column(self.ttn, print))
|
|
90
|
+ self.assertFalse(sw.add_column(self.ttn, ['foo', 'integer']))
|
|
91
|
+ self.assertFalse(sw.add_column(self.ttn, None))
|
|
92
|
+ self.assertFalse(sw.add_column(self.ttn, 42))
|
|
93
|
+ self.assertFalse(sw.add_column(1, {'name':'foo', 'type':'integer'}))
|
|
94
|
+ self.assertFalse(sw.add_column(print, {'name':'foo', 'type':'integer'}))
|
|
95
|
+ self.assertFalse(sw.add_column([], {'name':'foo', 'type':'integer'}))
|
|
96
|
+ self.assertFalse(sw.add_column(dict(), {'name':'foo', 'type':'integer'}))
|
|
97
|
+ for badname in NAMEINJECT:
|
|
98
|
+ self.assertFalse(sw.add_column(self.ttn, {'name':badname, 'type':'INTEGER'}))
|
|
99
|
+ self.assertFalse(sw.add_column(self.ttn, {'name':coolname+str(i), 'type':badname}))
|
|
100
|
+ self.assertFalse(sw.add_column(badname, {'name':coolname+str(i), 'type':'INTEGER'}))
|
|
101
|
+ i+=1
|
|
102
|
+
|
|
103
|
+ @unittest.skip('dev') #TODO remove skip
|
|
104
|
+ def test_alter_column(self):
|
|
105
|
+ sw = SqlWrapper()
|
|
106
|
+
|
|
107
|
+ colnames = ['talter', 'talter1', 'test_alter', 'test-alter-col', '-test_alter', '__test_alter__']
|
|
108
|
+ for i,name in enumerate(random.sample(colnames, len(colnames))):
|
|
109
|
+ col = { 'name': name, 'type': VTYPES[i%len(VTYPES)] }
|
|
110
|
+ self.assertTrue(sw.add_column( self.ttn, col))
|
|
111
|
+
|
|
112
|
+ for i,name in enumerate(random.sample(colnames, len(colnames))):
|
|
113
|
+ col = {'name': name, 'type': VTYPES[i%len(VTYPES)]}
|
|
114
|
+ self.assertTrue(self.ttn, col)
|
|
115
|
+ pass
|
|
116
|
+
|
|
117
|
+ @unittest.skip('dev') #TODO remove skip
|
|
118
|
+ def test_alter_column_badargs(self):
|
|
119
|
+ sw = SqlWrapper()
|
|
120
|
+
|
|
121
|
+ colnames = ['tabad', 'tabad1']
|
|
122
|
+
|
|
123
|
+ for i,name in enumerate(colnames):
|
|
124
|
+ col = { 'name': name, 'type': VTYPES[i%len(VTYPES)] }
|
|
125
|
+ self.assertTrue(sw.add_column(self.ttn, col))
|
|
126
|
+
|
|
127
|
+ for i,badname in enumerate(NAMEINJECT):
|
|
128
|
+ col = { 'name': badname, 'type': VTYPES[i%len(VTYPES)] }
|
|
129
|
+ self.assertFalse(sw.alter_column(self.ttn, col))
|
|
130
|
+
|
|
131
|
+ col = { 'name': colnames[i%len(colnames)], 'type': badname}
|
|
132
|
+ self.assertFalse(sw.alter_column(self.ttn, col))
|
|
133
|
+
|
|
134
|
+ col = { 'name': badname, 'type': NAMEINJECT[random.randint(0,len(NAMEINJECT))]}
|
|
135
|
+ self.assertFalse(sw.alter_column(self.ttn, col))
|
|
136
|
+
|
|
137
|
+ col = { 'name': colnames[i%len(colnames)], 'type': VTYPES[i%len(VTYPES)] }
|
|
138
|
+ self.assertFalse(sw.alter_column(badname, col))
|
|
139
|
+
|
|
140
|
+ def test_insert(self):
|
|
141
|
+ sw = SqlWrapper()
|
|
142
|
+
|
|
143
|
+ records = [
|
|
144
|
+ { 'pk': 0,
|
|
145
|
+ 'testchr': 'Hello world !',
|
|
146
|
+ 'testtext': 'Wow ! Super text... I\'m amazed',
|
|
147
|
+ 'testbool': False
|
|
148
|
+ },
|
|
149
|
+ { 'pk': 1,
|
|
150
|
+ 'testchr': 'Hello"world...--',
|
|
151
|
+ 'testtext': 'Another wonderfull text. But this time with spécials chars@;,:--*/+\'{}]{[|~&ù^$*µ$£ê;<ç>\/*-+',
|
|
152
|
+ 'testbool': True
|
|
153
|
+ },
|
|
154
|
+ { 'pk': 2 }, #default values for others
|
|
155
|
+ { 'pk': '3',
|
|
156
|
+ 'testchr': None,
|
|
157
|
+ 'testtext': None,
|
|
158
|
+ 'testbool': 'true'
|
|
159
|
+ },
|
|
160
|
+ { 'pk': 4,
|
|
161
|
+ 'testchr': '',
|
|
162
|
+ 'testtext': '',
|
|
163
|
+ 'testbool': 'false'
|
|
164
|
+ },
|
|
165
|
+ { 'pk': 5,
|
|
166
|
+ 'testbool': 0
|
|
167
|
+ },
|
|
168
|
+ { 'pk': 6,
|
|
169
|
+ 'testbool': 1
|
|
170
|
+ },
|
|
171
|
+ { 'pk':1024,
|
|
172
|
+ 'testbool': False
|
|
173
|
+ },
|
|
174
|
+ ]
|
|
175
|
+
|