~ubuntu-branches/ubuntu/trusty/mysql-5.6/trusty

« back to all changes in this revision

Viewing changes to unittest/gunit/get_diagnostics-t.cc

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-02-12 11:54:27 UTC
  • Revision ID: package-import@ubuntu.com-20140212115427-oq6tfsqxl1wuwehi
Tags: upstream-5.6.15
ImportĀ upstreamĀ versionĀ 5.6.15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 2011, 2013, 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 as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
15
 
 
16
// First include (the generated) my_config.h, to get correct platform defines.
 
17
#include "my_config.h"
 
18
#include <gtest/gtest.h>
 
19
 
 
20
#include "test_utils.h"
 
21
 
 
22
#include "item.h"
 
23
#include "sql_get_diagnostics.h"
 
24
 
 
25
namespace get_diagnostics_unittest {
 
26
 
 
27
using my_testing::Server_initializer;
 
28
using my_testing::Mock_error_handler;
 
29
 
 
30
class GetDiagnosticsTest : public ::testing::Test
 
31
{
 
32
protected:
 
33
  virtual void SetUp() { initializer.SetUp(); }
 
34
  virtual void TearDown() { initializer.TearDown(); }
 
35
 
 
36
  THD *thd() { return initializer.thd(); }
 
37
 
 
38
  Server_initializer initializer;
 
39
};
 
40
 
 
41
 
 
42
class FailHelper
 
43
{
 
44
public:
 
45
  void fail(const char *message)
 
46
  {
 
47
    FAIL() << message;
 
48
  }
 
49
};
 
50
 
 
51
 
 
52
LEX_STRING var_name1= {C_STRING_WITH_LEN("var1")};
 
53
LEX_STRING var_name2= {C_STRING_WITH_LEN("var2")};
 
54
 
 
55
 
 
56
class MockDiagInfoItem : public Diagnostics_information_item
 
57
{
 
58
public:
 
59
  MockDiagInfoItem(Item *target, int value)
 
60
    : Diagnostics_information_item(target), m_value(value)
 
61
  {}
 
62
 
 
63
  Item *get_value(THD *thd, const Diagnostics_area *da)
 
64
  {
 
65
    return new (thd->mem_root) Item_int(m_value);
 
66
  }
 
67
 
 
68
private:
 
69
  int m_value;
 
70
};
 
71
 
 
72
 
 
73
class MockDiagInfo : public Diagnostics_information,
 
74
                     private FailHelper
 
75
{
 
76
public:
 
77
  MockDiagInfo(List<MockDiagInfoItem> *items)
 
78
    : m_items(items)
 
79
  {}
 
80
 
 
81
protected:
 
82
  bool aggregate(THD *thd, const Diagnostics_area *da)
 
83
  {
 
84
    bool rv= false;
 
85
    MockDiagInfoItem *diag_info_item;
 
86
    List_iterator<MockDiagInfoItem> it(*m_items);
 
87
 
 
88
    while ((diag_info_item= it++))
 
89
    {
 
90
      if ((rv= evaluate(thd, diag_info_item, da)))
 
91
        break;
 
92
    }
 
93
 
 
94
    return rv;
 
95
  }
 
96
 
 
97
  ~MockDiagInfo()
 
98
  {
 
99
    fail("MockDiagInfo destructor invoked.");
 
100
  }
 
101
 
 
102
private:
 
103
  List<MockDiagInfoItem> *m_items;
 
104
};
 
105
 
 
106
 
 
107
// GET [CURRENT] DIAGNOSTICS @var1 = 1, @var2 = 2;
 
108
TEST_F(GetDiagnosticsTest, Cmd)
 
109
{
 
110
  Item *var;
 
111
  Sql_cmd *cmd;
 
112
  MockDiagInfo *info;
 
113
  MockDiagInfoItem *diag_info_item;
 
114
  List<MockDiagInfoItem> items;
 
115
  MEM_ROOT *mem_root= thd()->mem_root;
 
116
 
 
117
  // set var1 item
 
118
  var= new (mem_root) Item_func_get_user_var(var_name1);
 
119
  diag_info_item= new (mem_root) MockDiagInfoItem(var, 1);
 
120
  EXPECT_FALSE(items.push_back(diag_info_item));
 
121
 
 
122
  // set var2 item
 
123
  var= new (mem_root) Item_func_get_user_var(var_name2);
 
124
  diag_info_item= new (mem_root) MockDiagInfoItem(var, 2);
 
125
  EXPECT_FALSE(items.push_back(diag_info_item));
 
126
 
 
127
  // Information list and command
 
128
  info= new (mem_root) MockDiagInfo(&items);
 
129
  info->set_which_da(Diagnostics_information::CURRENT_AREA);
 
130
  cmd= new (mem_root) Sql_cmd_get_diagnostics(info);
 
131
 
 
132
  EXPECT_FALSE(cmd->execute(thd()));
 
133
  EXPECT_TRUE(thd()->get_stmt_da()->is_ok());
 
134
 
 
135
  // check var1 value
 
136
  var= new (mem_root) Item_func_get_user_var(var_name1);
 
137
  EXPECT_FALSE(var->fix_fields(thd(), &var));
 
138
  EXPECT_EQ(1, var->val_int());
 
139
 
 
140
  // check var2 value
 
141
  var= new (mem_root) Item_func_get_user_var(var_name2);
 
142
  EXPECT_FALSE(var->fix_fields(thd(), &var));
 
143
  EXPECT_EQ(2, var->val_int());
 
144
}
 
145
 
 
146
 
 
147
// Verifies death with a DBUG_ASSERT if target item is not settable.
 
148
// Google Test recommends DeathTest suffix for classes used in death tests.
 
149
typedef GetDiagnosticsTest GetDiagnosticsTestDeathTest;
 
150
 
 
151
#if GTEST_HAS_DEATH_TEST && !defined(DBUG_OFF)
 
152
TEST_F(GetDiagnosticsTestDeathTest, DieWhenUnsettableItem)
 
153
{
 
154
  Item *var;
 
155
  Sql_cmd *cmd;
 
156
  MockDiagInfo *info;
 
157
  MockDiagInfoItem *diag_info_item;
 
158
  List<MockDiagInfoItem> items;
 
159
  MEM_ROOT *mem_root= thd()->mem_root;
 
160
 
 
161
  ::testing::FLAGS_gtest_death_test_style= "threadsafe";
 
162
 
 
163
  // Unsettable item
 
164
  var= new (mem_root) Item_int(1);
 
165
  diag_info_item= new (mem_root) MockDiagInfoItem(var, 1);
 
166
  EXPECT_FALSE(items.push_back(diag_info_item));
 
167
 
 
168
  // Information list and command
 
169
  info= new (mem_root) MockDiagInfo(&items);
 
170
  info->set_which_da(Diagnostics_information::CURRENT_AREA);
 
171
  cmd= new (mem_root) Sql_cmd_get_diagnostics(info);
 
172
 
 
173
  EXPECT_DEATH(cmd->execute(thd()), ".*Assertion.*srp.*");
 
174
}
 
175
#endif  // GTEST_HAS_DEATH_TEST && !defined(DBUG_OFF)
 
176
 
 
177
 
 
178
class MockDiagInfoError : public Diagnostics_information
 
179
{
 
180
public:
 
181
  MockDiagInfoError(bool fatal_error)
 
182
    : m_fatal_error(fatal_error)
 
183
  {}
 
184
 
 
185
protected:
 
186
  bool aggregate(THD *thd, const Diagnostics_area *)
 
187
  {
 
188
    myf flag= m_fatal_error ? MYF(ME_FATALERROR) : MYF(0);
 
189
    my_message_sql(ER_UNKNOWN_ERROR, "Unknown error", flag);
 
190
    return thd->is_error();
 
191
  }
 
192
 
 
193
private:
 
194
  bool m_fatal_error;
 
195
};
 
196
 
 
197
 
 
198
// GET DIAGNOSTICS itself causes an error.
 
199
TEST_F(GetDiagnosticsTest, Error)
 
200
{
 
201
  Sql_cmd *cmd;
 
202
  MockDiagInfoError *info;
 
203
  MEM_ROOT *mem_root= thd()->mem_root;
 
204
 
 
205
  // Pre-existing warning
 
206
  push_warning_printf(thd(), Sql_condition::WARN_LEVEL_WARN,
 
207
                      WARN_DATA_TRUNCATED, "Data truncated");
 
208
 
 
209
  // Simulate GET DIAGNOSTICS as a new command separated
 
210
  // from the one that generated the warning
 
211
  thd()->reset_for_next_command();
 
212
 
 
213
  // Error bound "information" and command
 
214
  info= new (mem_root) MockDiagInfoError(false);
 
215
  info->set_which_da(Diagnostics_information::CURRENT_AREA);
 
216
  cmd= new (mem_root) Sql_cmd_get_diagnostics(info);
 
217
 
 
218
  initializer.set_expected_error(ER_UNKNOWN_ERROR);
 
219
 
 
220
  // Should succeed, not a fatal error
 
221
  EXPECT_FALSE(cmd->execute(thd()));
 
222
  EXPECT_TRUE(thd()->get_stmt_da()->is_ok());
 
223
 
 
224
  // New condition for the error
 
225
  EXPECT_EQ(1U, thd()->get_stmt_da()->statement_warn_count());
 
226
 
 
227
  // Counted as a error
 
228
  EXPECT_EQ(1U, thd()->get_stmt_da()->error_count());
 
229
 
 
230
  // Error is appended
 
231
  EXPECT_EQ(2U, thd()->get_stmt_da()->warn_count());
 
232
}
 
233
 
 
234
 
 
235
// GET DIAGNOSTICS itself causes a fatal error.
 
236
TEST_F(GetDiagnosticsTest, FatalError)
 
237
{
 
238
  Sql_cmd *cmd;
 
239
  MockDiagInfoError *info;
 
240
  MEM_ROOT *mem_root= thd()->mem_root;
 
241
 
 
242
  // Pre-existing warning
 
243
  push_warning_printf(thd(), Sql_condition::WARN_LEVEL_WARN,
 
244
                      WARN_DATA_TRUNCATED, "Data truncated");
 
245
 
 
246
  // Simulate GET DIAGNOSTICS as a new command separated
 
247
  // from the one that generated the warning
 
248
  thd()->reset_for_next_command();
 
249
 
 
250
  // Error bound "information" and command
 
251
  info= new (mem_root) MockDiagInfoError(true);
 
252
  info->set_which_da(Diagnostics_information::CURRENT_AREA);
 
253
  cmd= new (mem_root) Sql_cmd_get_diagnostics(info);
 
254
 
 
255
  initializer.set_expected_error(ER_UNKNOWN_ERROR);
 
256
 
 
257
  // Should not succeed due to a fatal error
 
258
  EXPECT_TRUE(cmd->execute(thd()));
 
259
  EXPECT_TRUE(thd()->get_stmt_da()->is_error());
 
260
 
 
261
  // No new condition for the error
 
262
  EXPECT_EQ(0U, thd()->get_stmt_da()->error_count());
 
263
 
 
264
  // Fatal error is set, not appended
 
265
  EXPECT_EQ(1U, thd()->get_stmt_da()->warn_count());
 
266
}
 
267
 
 
268
 
 
269
// GET [CURRENT] DIAGNOSTICS @var1 = NUMBER, @var2 = ROW_COUNT;
 
270
TEST_F(GetDiagnosticsTest, StatementInformation)
 
271
{
 
272
  Item *var;
 
273
  Sql_cmd *cmd;
 
274
  Statement_information *info;
 
275
  Statement_information_item *diag_info_item;
 
276
  List<Statement_information_item> items;
 
277
  MEM_ROOT *mem_root= thd()->mem_root;
 
278
 
 
279
  // NUMBER = 1 warning
 
280
  thd()->raise_warning(ER_UNKNOWN_ERROR);
 
281
  // ROW_COUNT = 5
 
282
  thd()->set_row_count_func(5U);
 
283
 
 
284
  // var1 will receive the value of NUMBER
 
285
  var= new (mem_root) Item_func_get_user_var(var_name1);
 
286
  diag_info_item= new (mem_root)
 
287
    Statement_information_item(Statement_information_item::NUMBER, var);
 
288
  EXPECT_FALSE(items.push_back(diag_info_item));
 
289
 
 
290
  // var2 will receive the value of ROW_COUNT
 
291
  var= new (mem_root) Item_func_get_user_var(var_name2);
 
292
  diag_info_item= new (mem_root)
 
293
    Statement_information_item(Statement_information_item::ROW_COUNT, var);
 
294
  EXPECT_FALSE(items.push_back(diag_info_item));
 
295
 
 
296
  // Information list and command
 
297
  info= new (mem_root) Statement_information(&items);
 
298
  info->set_which_da(Diagnostics_information::CURRENT_AREA);
 
299
  cmd= new (mem_root) Sql_cmd_get_diagnostics(info);
 
300
 
 
301
  EXPECT_FALSE(cmd->execute(thd()));
 
302
  EXPECT_TRUE(thd()->get_stmt_da()->is_ok());
 
303
 
 
304
  // check var1 value
 
305
  var= new (mem_root) Item_func_get_user_var(var_name1);
 
306
  EXPECT_FALSE(var->fix_fields(thd(), &var));
 
307
  EXPECT_EQ(1U, var->val_uint());
 
308
 
 
309
  // check var2 value
 
310
  var= new (mem_root) Item_func_get_user_var(var_name2);
 
311
  EXPECT_FALSE(var->fix_fields(thd(), &var));
 
312
  EXPECT_EQ(5U, var->val_int());
 
313
}
 
314
 
 
315
 
 
316
// GET DIAGNOSTICS CONDITION 1 @var1 = MYSQL_ERRNO, @var2 = MESSAGE_TEXT;
 
317
TEST_F(GetDiagnosticsTest, ConditionInformation)
 
318
{
 
319
  Item *var;
 
320
  String str;
 
321
  Sql_cmd *cmd;
 
322
  Condition_information *info;
 
323
  Condition_information_item *diag_info_item;
 
324
  List<Condition_information_item> items;
 
325
  MEM_ROOT *mem_root= thd()->mem_root;
 
326
 
 
327
  // Pre-existing error
 
328
  my_message_sql(ER_UNKNOWN_ERROR, "Unknown error", MYF(0));
 
329
 
 
330
  // Simulate GET DIAGNOSTICS as a new command separated
 
331
  // from the one that generated the error
 
332
  thd()->reset_for_next_command();
 
333
 
 
334
  // var1 will receive the value of MYSQL_ERRNO
 
335
  var= new (mem_root) Item_func_get_user_var(var_name1);
 
336
  diag_info_item= new (mem_root)
 
337
    Condition_information_item(Condition_information_item::MYSQL_ERRNO, var);
 
338
  EXPECT_FALSE(items.push_back(diag_info_item));
 
339
 
 
340
  // var2 will receive the value of MESSAGE_TEXT
 
341
  var= new (mem_root) Item_func_get_user_var(var_name2);
 
342
  diag_info_item= new (mem_root)
 
343
    Condition_information_item(Condition_information_item::MESSAGE_TEXT, var);
 
344
  EXPECT_FALSE(items.push_back(diag_info_item));
 
345
 
 
346
  // condition number (1)
 
347
  var= new (mem_root) Item_uint(1);
 
348
 
 
349
  // Information list and command
 
350
  info= new (mem_root) Condition_information(var, &items);
 
351
  info->set_which_da(Diagnostics_information::CURRENT_AREA);
 
352
  cmd= new (mem_root) Sql_cmd_get_diagnostics(info);
 
353
 
 
354
  EXPECT_FALSE(cmd->execute(thd()));
 
355
  EXPECT_TRUE(thd()->get_stmt_da()->is_ok());
 
356
 
 
357
  // check var1 value
 
358
  var= new (mem_root) Item_func_get_user_var(var_name1);
 
359
  EXPECT_FALSE(var->fix_fields(thd(), &var));
 
360
  EXPECT_EQ(ulonglong (ER_UNKNOWN_ERROR), var->val_uint());
 
361
 
 
362
  // check var2 value
 
363
  var= new (mem_root) Item_func_get_user_var(var_name2);
 
364
  EXPECT_FALSE(var->fix_fields(thd(), &var));
 
365
  EXPECT_EQ(&str, var->val_str(&str));
 
366
  EXPECT_STREQ("Unknown error", str.c_ptr_safe());
 
367
}
 
368
 
 
369
 
 
370
Item *get_cond_info_item(THD *thd,
 
371
                         uint number,
 
372
                         Condition_information_item::Name name)
 
373
{
 
374
  Item *var;
 
375
  Sql_cmd *cmd;
 
376
  Condition_information *info;
 
377
  Condition_information_item *diag_info_item;
 
378
  List<Condition_information_item> items;
 
379
  MEM_ROOT *mem_root= thd->mem_root;
 
380
  LEX_STRING var_name= {C_STRING_WITH_LEN("get_cond_info_item")};
 
381
 
 
382
  // Simulate GET DIAGNOSTICS as a new command
 
383
  thd->reset_for_next_command();
 
384
 
 
385
  // var1 will receive the value of MYSQL_ERRNO
 
386
  var= new (mem_root) Item_func_get_user_var(var_name);
 
387
  diag_info_item= new (mem_root) Condition_information_item(name, var);
 
388
  EXPECT_FALSE(items.push_back(diag_info_item));
 
389
 
 
390
  // condition number
 
391
  var= new (mem_root) Item_uint(number);
 
392
 
 
393
  // Information list and command
 
394
  info= new (mem_root) Condition_information(var, &items);
 
395
  info->set_which_da(Diagnostics_information::CURRENT_AREA);
 
396
  cmd= new (mem_root) Sql_cmd_get_diagnostics(info);
 
397
 
 
398
  EXPECT_FALSE(cmd->execute(thd));
 
399
  EXPECT_TRUE(thd->get_stmt_da()->is_ok());
 
400
 
 
401
  // make a user var item
 
402
  var= new (mem_root) Item_func_get_user_var(var_name);
 
403
  EXPECT_FALSE(var->fix_fields(thd, &var));
 
404
 
 
405
  return var;
 
406
}
 
407
 
 
408
 
 
409
// GET DIAGNOSTICS CONDITION 1 @var = CLASS_ORIGIN;
 
410
// GET DIAGNOSTICS CONDITION 1 @var = SUBCLASS_ORIGIN;
 
411
TEST_F(GetDiagnosticsTest, ConditionInformationClassOrigin)
 
412
{
 
413
  Item *var;
 
414
  String str;
 
415
 
 
416
  // "MySQL" origin
 
417
  push_warning_printf(thd(), Sql_condition::WARN_LEVEL_WARN,
 
418
                      ER_XAER_NOTA, "Unknown XID");
 
419
 
 
420
  // "ISO 9075" origin
 
421
  push_warning_printf(thd(), Sql_condition::WARN_LEVEL_WARN,
 
422
                      ER_UNKNOWN_ERROR, "Unknown error");
 
423
 
 
424
  // Condition 1 CLASS_ORIGIN
 
425
  var= get_cond_info_item(thd(), 1, Condition_information_item::CLASS_ORIGIN);
 
426
  EXPECT_EQ(&str, var->val_str(&str));
 
427
  EXPECT_STREQ("MySQL", str.c_ptr_safe());
 
428
 
 
429
  // Condition 1 SUBCLASS_ORIGIN
 
430
  var= get_cond_info_item(thd(), 1, Condition_information_item::SUBCLASS_ORIGIN);
 
431
  EXPECT_EQ(&str, var->val_str(&str));
 
432
  EXPECT_STREQ("MySQL", str.c_ptr_safe());
 
433
 
 
434
  // Condition 2 CLASS_ORIGIN
 
435
  var= get_cond_info_item(thd(), 2, Condition_information_item::CLASS_ORIGIN);
 
436
  EXPECT_EQ(&str, var->val_str(&str));
 
437
  EXPECT_STREQ("ISO 9075", str.c_ptr_safe());
 
438
 
 
439
  // Condition 2 CLASS_ORIGIN
 
440
  var= get_cond_info_item(thd(), 2, Condition_information_item::SUBCLASS_ORIGIN);
 
441
  EXPECT_EQ(&str, var->val_str(&str));
 
442
  EXPECT_STREQ("ISO 9075", str.c_ptr_safe());
 
443
}
 
444
 
 
445
 
 
446
}