1 /* Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software Foundation,
21    51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
22 
23 // First include (the generated) my_config.h, to get correct platform defines,
24 // then gtest.h (before any other MySQL headers), to avoid min() macros etc ...
25 #include "my_config.h"
26 #include <gtest/gtest.h>
27 #include <gmock/gmock.h>
28 
29 #include "mock_field_timestamp.h"
30 #include "fake_table.h"
31 #include "test_utils.h"
32 #include "sql_data_change.h"
33 
34 namespace copy_info_unittest {
35 
36 using my_testing::Server_initializer;
37 using my_testing::Mock_error_handler;
38 
39 using ::testing::StrictMock;
40 using ::testing::_;
41 
42 /*
43   Tests for the functionality of the COPY_INFO class. We test all public
44   interfaces, and some of the protected parts:
45 
46   - COPY_INFO::get_function_default_columns, and
47   - COPY_INFO::get_cached_bitmap
48 */
49 class CopyInfoTest : public ::testing::Test
50 {
51 protected:
SetUp()52   virtual void SetUp() { initializer.SetUp(); }
TearDown()53   virtual void TearDown() { initializer.TearDown(); }
54 
55   Server_initializer initializer;
56 };
57 
58 
59 /**
60   This is a simple mock Field class, which verifies that store_timestamp is
61   called. We inherit Field_long, but the data type does not matter.
62 */
63 class Mock_field : public Field_long
64 {
65   uchar null_byte;
66 public:
67 
Mock_field(utype unireg)68   Mock_field(utype unireg) :
69     Field_long(NULL, 0, &null_byte, 0, unireg, "", false,  false)
70   {}
71 
72   MOCK_METHOD1(store_timestamp, void(const timeval*));
73 };
74 
75 
76 /*
77   Compares two COPY_INFO::Statistics and makes sure they are equal.
78 */
check_equality(const COPY_INFO::Statistics a,const COPY_INFO::Statistics b)79 void check_equality(const COPY_INFO::Statistics a,
80                     const COPY_INFO::Statistics b)
81 {
82   EXPECT_EQ(a.records, b.records);
83   EXPECT_EQ(a.deleted, b.deleted);
84   EXPECT_EQ(a.updated, b.updated);
85   EXPECT_EQ(a.copied,  b.copied);
86   EXPECT_EQ(a.error_count, b.error_count);
87   EXPECT_EQ(a.touched, b.touched);
88 }
89 
90 
91 /*
92   Convenience class for creating a COPY_INFO to represent an insert operation.
93 */
94 class Mock_COPY_INFO: public COPY_INFO
95 {
96 public:
Mock_COPY_INFO(operation_type optype,List<Item> * inserted_columns,enum_duplicates duplicate_handling)97   Mock_COPY_INFO(operation_type optype,
98                  List<Item> *inserted_columns,
99                  enum_duplicates duplicate_handling)
100     : COPY_INFO(optype,
101                 inserted_columns,
102                 true, // manage_defaults
103                 duplicate_handling)
104   {}
105 
106   // Import protected member functions, so we can test them.
107   using COPY_INFO::get_function_default_columns;
108   using COPY_INFO::get_cached_bitmap;
109 };
110 
111 
112 /*
113   Convenience class for creating a COPY_INFO to represent an insert operation.
114 */
115 class Mock_COPY_INFO_insert : public COPY_INFO
116 {
117 public:
Mock_COPY_INFO_insert()118   Mock_COPY_INFO_insert() :
119     COPY_INFO(COPY_INFO::INSERT_OPERATION, static_cast<List<Item>*>(NULL),
120               true, // manage_defaults
121               DUP_UPDATE)
122   {}
Mock_COPY_INFO_insert(List<Item> * fields)123   Mock_COPY_INFO_insert(List<Item> *fields) :
124     COPY_INFO(COPY_INFO::INSERT_OPERATION, fields,
125               true, // manage_defaults
126               DUP_UPDATE)
127   {}
128   // Import protected member functions, so we can test them.
129   using COPY_INFO::get_function_default_columns;
130   using COPY_INFO::get_cached_bitmap;
131 };
132 
133 
134 /*
135   Convenience class for creating a COPY_INFO to represent an update
136   operation.
137 */
138 class Mock_COPY_INFO_update : public COPY_INFO
139 {
140 public:
Mock_COPY_INFO_update()141   Mock_COPY_INFO_update()
142     : COPY_INFO(COPY_INFO::UPDATE_OPERATION, NULL, NULL)
143   {}
144   // Import protected member functions, so we can test them.
145   using COPY_INFO::get_function_default_columns;
146   using COPY_INFO::get_cached_bitmap;
147 };
148 
149 
150 /*
151   Tests that constuctors initialize the stats object properly.
152 */
TEST_F(CopyInfoTest,constructors)153 TEST_F(CopyInfoTest, constructors)
154 {
155   List<Item> inserted_columns;
156 
157   COPY_INFO insert(COPY_INFO::INSERT_OPERATION,
158                    &inserted_columns,
159                    true, // manage_defaults
160                    DUP_UPDATE);
161 
162   EXPECT_EQ(0U, insert.stats.records);
163   EXPECT_EQ(0U, insert.stats.deleted);
164   EXPECT_EQ(0U, insert.stats.updated);
165   EXPECT_EQ(0U, insert.stats.copied);
166   EXPECT_EQ(0U, insert.stats.error_count);
167   EXPECT_EQ(0U, insert.stats.touched);
168 
169   List<Item> columns;
170   List<Item> values;
171   COPY_INFO update(COPY_INFO::UPDATE_OPERATION, &columns, &values);
172 
173   EXPECT_EQ(0U, update.stats.records);
174   EXPECT_EQ(0U, update.stats.deleted);
175   EXPECT_EQ(0U, update.stats.updated);
176   EXPECT_EQ(0U, update.stats.copied);
177   EXPECT_EQ(0U, update.stats.error_count);
178   EXPECT_EQ(0U, update.stats.touched);
179 
180 }
181 
182 
183 /*
184   Tests the accessors when the COPY_INFO represents an insert operation.
185 */
TEST_F(CopyInfoTest,insertAccessors)186 TEST_F(CopyInfoTest, insertAccessors)
187 {
188   List<Item> inserted_columns;
189 
190   COPY_INFO insert(COPY_INFO::INSERT_OPERATION,
191                    &inserted_columns,
192                    true, // manage_defaults
193                    DUP_REPLACE);
194 
195   EXPECT_EQ(COPY_INFO::INSERT_OPERATION, insert.get_operation_type());
196   EXPECT_EQ(&inserted_columns, insert.get_changed_columns());
197   EXPECT_EQ(static_cast<List<Item>*>(NULL), insert.get_changed_columns2());
198   EXPECT_TRUE(insert.get_manage_defaults());
199   EXPECT_EQ(DUP_REPLACE, insert.get_duplicate_handling());
200 }
201 
202 
203 /*
204   Tests the accessors when the COPY_INFO represents a load data infile
205   operation.
206 */
TEST_F(CopyInfoTest,loadDataAccessors)207 TEST_F(CopyInfoTest, loadDataAccessors)
208 {
209   List<Item> inserted_columns;
210   List<Item> inserted_columns2;
211 
212   COPY_INFO load_data(COPY_INFO::INSERT_OPERATION,
213                       &inserted_columns,
214                       &inserted_columns2,
215                       true, // manage_defaults
216                       DUP_UPDATE,
217                       123);
218 
219   EXPECT_EQ(COPY_INFO::INSERT_OPERATION, load_data.get_operation_type());
220   EXPECT_EQ(&inserted_columns, load_data.get_changed_columns());
221   EXPECT_EQ(&inserted_columns2, load_data.get_changed_columns2());
222   EXPECT_TRUE(load_data.get_manage_defaults());
223   EXPECT_EQ(DUP_UPDATE, load_data.get_duplicate_handling());
224 }
225 
226 
227 /*
228   Tests the accessors when the COPY_INFO represents an update operation.
229 */
TEST_F(CopyInfoTest,updateAccessors)230 TEST_F(CopyInfoTest, updateAccessors)
231 {
232   List<Item> columns;
233   List<Item> values;
234 
235   COPY_INFO update(COPY_INFO::UPDATE_OPERATION, &columns, &values);
236 
237   EXPECT_EQ(COPY_INFO::UPDATE_OPERATION, update.get_operation_type());
238   EXPECT_EQ(&columns, update.get_changed_columns());
239   EXPECT_EQ(static_cast<List<Item>*>(NULL), update.get_changed_columns2());
240   EXPECT_TRUE(update.get_manage_defaults());
241   EXPECT_EQ(DUP_ERROR, update.get_duplicate_handling());
242 }
243 
244 
make_field()245 Field_long make_field()
246 {
247   static uchar unused_null_byte;
248 
249   Field_long a(NULL,
250                0,
251                &unused_null_byte,
252                0,
253                Field::TIMESTAMP_DN_FIELD,
254                "a",
255                false,
256                false);
257   return a;
258 }
259 
260 
261 /*
262   Test of the lazy instantiation performed by get_function_default_columns().
263 
264   - The bitmap pointer is initially NULL.
265 
266   - That calling get_function_default_columns() indeed points the member to a
267     lazily instantiated bitmap.
268 
269   - That on a second call to get_function_default_columns(), a new bitmap is
270     not allocated.
271 
272     We repeat the test for insert and update operations.
273 */
TEST_F(CopyInfoTest,getFunctionDefaultColumns)274 TEST_F(CopyInfoTest, getFunctionDefaultColumns)
275 {
276   Mock_COPY_INFO_insert insert;
277   Mock_COPY_INFO_update update;
278 
279   Field_long a= make_field();
280   Fake_TABLE table(&a);
281 
282   MY_BITMAP *initial_value= NULL;
283 
284   EXPECT_EQ(initial_value, insert.get_cached_bitmap());
285 
286   insert.get_function_default_columns(&table);
287   EXPECT_NE(initial_value, insert.get_cached_bitmap())
288     << "The output parameter must be set!";
289 
290   const MY_BITMAP *function_default_columns= insert.get_cached_bitmap();
291   insert.get_function_default_columns(&table);
292   EXPECT_EQ(function_default_columns, insert.get_cached_bitmap())
293     << "Not supposed to allocate a new bitmap on second call.";
294 
295   EXPECT_EQ(initial_value, update.get_cached_bitmap());
296   update.get_function_default_columns(&table);
297   EXPECT_NE(initial_value, update.get_cached_bitmap())
298     << "The output parameter must be set!";
299 
300   function_default_columns= update.get_cached_bitmap();
301   update.get_function_default_columns(&table);
302   EXPECT_EQ(function_default_columns, update.get_cached_bitmap())
303     << "Not supposed to allocate a new bitmap on second call.";
304 }
305 
306 
307 /*
308   Here we test that calling COPY_INFO::set_function_defaults() indeed causes
309   store_timestamp to be called on the columns that are not on the list of
310   assigned_columns. We seize the opportunity to test
311   COPY_INFO::function_defaults_apply() since we have to call it anyways in
312   order for set_function_defaults() not to assert.
313 */
TEST_F(CopyInfoTest,setFunctionDefaults)314 TEST_F(CopyInfoTest, setFunctionDefaults)
315 {
316   StrictMock<Mock_field> a(Field::TIMESTAMP_UN_FIELD);
317   StrictMock<Mock_field> b(Field::TIMESTAMP_DNUN_FIELD);
318   StrictMock<Mock_field> c(Field::TIMESTAMP_DNUN_FIELD);
319 
320   EXPECT_TRUE(a.has_update_default_function());
321   EXPECT_TRUE(b.has_update_default_function());
322   EXPECT_TRUE(c.has_update_default_function());
323 
324   Fake_TABLE table(&a, &b, &c);
325 
326   List<Item> assigned_columns;
327   assigned_columns.push_front(new Item_field(&a));
328 
329   Mock_COPY_INFO insert(COPY_INFO::INSERT_OPERATION,
330                         &assigned_columns,
331                         DUP_ERROR);
332 
333   ASSERT_FALSE(insert.get_function_default_columns(&table)) << "Out of memory";
334 
335   insert.ignore_last_columns(&table, 1); // 'c'
336   insert.add_function_default_columns(&table, table.write_set);
337   EXPECT_FALSE(bitmap_is_set(table.write_set, 0));
338   EXPECT_TRUE (bitmap_is_set(table.write_set, 1));
339   EXPECT_FALSE(bitmap_is_set(table.write_set, 2));
340 
341   EXPECT_TRUE(insert.function_defaults_apply(&table)) << "They do apply";
342 
343   // We expect store_timestamp() to be called for b and not for c.
344   // We do not care about the argument to store_timestamp().
345   EXPECT_CALL(b, store_timestamp(_)).Times(1);
346   EXPECT_CALL(c, store_timestamp(_)).Times(0);
347   insert.set_function_defaults(&table);
348 }
349 
350 }
351