File: test_db_mysql_schema_diff_reporting.cpp

package info (click to toggle)
mysql-workbench 6.3.8%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 113,932 kB
  • ctags: 87,814
  • sloc: ansic: 955,521; cpp: 427,465; python: 59,728; yacc: 59,129; xml: 54,204; sql: 7,091; objc: 965; makefile: 638; sh: 613; java: 237; perl: 30; ruby: 6; php: 1
file content (399 lines) | stat: -rw-r--r-- 13,657 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
/*
* Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of the
* License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301  USA
*/

#include <pcre.h>
#include "ctemplate/template.h"

#include "testgrt.h"
#include "grt_test_utility.h"
#include "grts/structs.db.mysql.h"
#include "grts/structs.workbench.physical.h"
#include "grts/structs.workbench.model.reporting.h"

#include "db_rev_eng_be.h"

// #include <diffsqlgen.h>

#include "grt_manager.h"
#include "wb_helpers.h"

#include "diffchange.h"
#include "grtdiff.h"
#include "changeobjects.h"
#include "changelistobjects.h"
// #include "dbobjectmatch.h"

using namespace std;

using ctemplate::Template;
using ctemplate::TemplateDictionary;
using ctemplate::STRIP_WHITESPACE;

// these functions are defined in grtdiff_alter_test.cpp
void populate_grt(GRT *grt, const char *);
// db_mysql_Catalog create_empty_catalog_for_import(grt::GRT *grt);
db_mysql_Catalog db_rev_eng_schema(bec::GRTManager *grtm, 
                                   const std::list<std::string>& schema_names);

//=============================================================================
//
//=============================================================================
BEGIN_TEST_DATA_CLASS(module_db_mysql_schema_diff_reporting)
public:
  GRTManagerTest grtm;
END_TEST_DATA_CLASS

TEST_MODULE(module_db_mysql_schema_diff_reporting, "DB MySQL: schema reporting");

//=============================================================================
// Test cases type for TEST_FUNCTION(5)
//=============================================================================
struct TestCase
{
  const char  *name;
  const char  *originalSQL;
  const char  *modifiedSQL;
  const char  *testExpression;
};

//-----------------------------------------------------------------------------
#if 0 // warning: unused variable 'testCases' [-Wunused-const-variable]
static const TestCase testCases[] =
{
  {
      "Drop test 1"
     ,"CREATE TABLE grtdiff_alter_test.to_be_dropped (id INT);"
     ,""
     ,"`to_be_dropped`\\s+was\\s+dropped"
  }
 ,{
      "Drop test 2"
     ,"CREATE TABLE grtdiff_alter_test.to_be_dropped (id INT);"
     ,""
     ,"`to_be_dropped`\\s+was\\s+dropped"
  }
 ,{
      "Alter engine"
     ,"CREATE TABLE grtdiff_alter_test.alter_table_engine (id INT) engine=myisam;"
     ,"CREATE TABLE grtdiff_alter_test.alter_table_engine (id INT) engine=innodb;"
     ,"alter_table_engine.*modified.*engine.*myisam.*innodb"
  }
 ,{
      "Alter table delay key write"
     ,"CREATE TABLE grtdiff_alter_test.alter_table_delay_key_write (id INT) delay_key_write=0;"
     ,""
     ,"alter_table_delay_key_write.*was dropped"
  }
 ,{
      "Create charset"
     ,"CREATE TABLE grtdiff_alter_test.alter_table_charset (id INT) default charset utf8;"
     ,"CREATE TABLE grtdiff_alter_test.alter_table_charset (id INT) default charset ascii;"
     ,"alter_table_charset.*was modified.*default character set.*utf8.*ascii"
  }
 ,{
      "Create collate"
     ,"CREATE TABLE grtdiff_alter_test.alter_table_collate (id INT) collate utf8_general_ci;"
     ,"CREATE TABLE grtdiff_alter_test.alter_table_collate (id INT) collate ascii_general_ci;"
     ,"alter_table_collate.*was modified.*default character set.*utf8.*ascii"
  }
 ,{
      "Create avg_row_length"
     ,"CREATE TABLE grtdiff_alter_test.alter_table_avg_row_length (id INT) avg_row_length=1;"
     ,"CREATE TABLE grtdiff_alter_test.alter_table_avg_row_length (id INT) avg_row_length=2;"
     ,"alter_table_avg_row_length.*was modified.*average row length: 1 --> 2"
  }
 ,{
      "Create table test 1"    
     ,""
     ,"CREATE TABLE grtdiff_alter_test.t1 (id INT);"
     ,"t1.? was created.*id of type INT"
  }
 ,{
     "Create table test 2"
    ,""
    ,"CREATE TABLE grtdiff_alter_test.t2 (id INT, id2 INT(11), val VARCHAR(255), t TEXT) ENGINE=MyISAM;"
    ,"t2.? was created.*id of type INT.*id2 of type INT.*val of type VARCHAR.*t of type TEXT"
  }
 ,{
     "Create table index test"
    ,""
    ,"CREATE TABLE grtdiff_alter_test.t3 (id INT, id2 INT(11), INDEX ix1 (id, id2 DESC));"
    ,"t3.? was created.*id of type INT.*id2 of type INT.*indices.*ix1 with columns:\\s+id,\\s+id2\\s+.?desc.?" // \(desc\)
  }
 ,{
    "Create table test foreign keys"
   ,""
   ,"CREATE TABLE grtdiff_alter_test.t3 (id INT, id2 INT(11), INDEX ix1 (id, id2 DESC)); CREATE TABLE grtdiff_alter_test.t4 (id INT, id2 INT(11), INDEX ix1 (id, id2 DESC), CONSTRAINT fk1 FOREIGN KEY(id, id2) REFERENCES t3(id, id2));"
   ,"t4.? was created.*id of type INT.*id2 of type INT.*indices.*ix1 with columns:\\s+id,\\s+id2\\s+.?desc.?.*foreign keys.*fk1 with columns.*id.*id2.*referred table.*t3.*id.*id2"
  }
 ,{
    "Create table test auto_increment and pass"
   ,"" 
   ,"CREATE TABLE grtdiff_alter_test.t1 (id int) auto_increment=3;"
   ,"next auto increment.*3"
  }
 ,{
   "Alter table test: column modified"
   ,"CREATE TABLE grtdiff_alter_test.t1 (id int);"
   ,"CREATE TABLE grtdiff_alter_test.t1 (id float);"
   ,"FIX ME"
  }
 ,{
   "Alter table test: columnt added, column deleted"
   ,"CREATE TABLE grtdiff_alter_test.t1 (id int);"
   ,"CREATE TABLE grtdiff_alter_test.t1 (id2 int);"
   ,"added column id2 of type INT.*removed column id"
  }
 ,{
   "Alter table test: index added"
   ,"CREATE TABLE grtdiff_alter_test.t1 (id int);"
   ,"CREATE TABLE grtdiff_alter_test.t1 (id int primary key);"
   ,"added index PRIMARY with columns: id"
  }
 ,{
   "Alter table test: index removed"
   ,"CREATE TABLE grtdiff_alter_test.t1 (id int primary key);"
   ,"CREATE TABLE grtdiff_alter_test.t1 (id int);"
   ,"removed index PRIMARY !FIELD NAME!"
  }
 ,{
   "Alter table test: added foreign key"
   ,"CREATE TABLE grtdiff_alter_test.t2 (id int); CREATE TABLE grtdiff_alter_test.t1 (id int);"
   ,"CREATE TABLE grtdiff_alter_test.t2 (id int); CREATE TABLE grtdiff_alter_test.t1 (id int references grtdiff_alter_test.t2(id));"
   ,"added foreign key  with columns: id, referred table: t2 with columns: id"
  }
 ,{
   "Alter table test: removed foreign key"
   ,"CREATE TABLE grtdiff_alter_test.t2 (id int); CREATE TABLE grtdiff_alter_test.t1 (id int references grtdiff_alter_test.t2(id));"
   ,"CREATE TABLE grtdiff_alter_test.t2 (id int); CREATE TABLE grtdiff_alter_test.t1 (id int);"
   ,"removed index KEY NAME"
  }
 ,{
   "Create table test: attributes auto_inrement, avg_row_length, delay_key_write"
   ,""
   ,"CREATE TABLE grtdiff_alter_test.t1(id int primary key) auto_increment=2 avg_row_length=8 delay_key_write=1;"
   ,"next auto increment.*2.*delay key writes.*1.*average row length.*8"
  }
 ,{
   "Create table test: attributes checksum, min_rows, max_rows, comment, pack_keys, row_format"
   ,""
   ,"CREATE TABLE grtdiff_alter_test.t1(id int primary key) checksum=1 comment='cmt' max_rows=5 min_rows=1 pack_keys=1 row_format=fixed;"
   ,"pack keys.*1.*checksum.*1.*row format.*fixed.*min rows.*1.*max rows.*5.*comment.*cmt"
  }
 ,{
   "Create table test: attributes insert_method"
   ,""
   ,"CREATE TABLE grtdiff_alter_test.t1(id int primary key) insert_method=last;"
   ,"merge insert method.*last"
  }
 ,{
   "Create table test: attributes"
   ,""
   ,"CREATE TABLE grtdiff_alter_test.t1(id int primary key) engine=myisam key_block_size=8 union=t2 data_directory=/var index_directory=/index connection='host 192.168.0.2';"
   ,"FIX ME"
  }
 ,{
    "Create trigger"
   ,""
   ,"create trigger grtdiff_alter_test.t1_trig after update on grtdiff_alter_test.t1 for each row insert into grtdiff_alter_test.t2 select max(grtdiff_alter_test.t1.id) from grtdiff_alter_test.t1;"
   ,"[Tt]rigger.*grtdiff_alter_test.*t1_trig.*created"
  }
 ,{
    "Drop trigger"
   ,"create trigger grtdiff_alter_test.t1_trig after update on grtdiff_alter_test.t1 for each row insert into grtdiff_alter_test.t2 select max(grtdiff_alter_test.t1.id) from grtdiff_alter_test.t1;"
   ,""
   ,"[Tt]rigger.*grtdiff_alter_test.*t1_trig.*dropped"
  }
 ,{
    "Create view"
   ,""
   ,"CREATE VIEW grtdiff_alter_test.t1v as select * from grtdiff_alter_test.t1;"
   ,"[Vv]iew.*t1v.*created"
  }
 ,{
    "Drop view"
   ,"CREATE VIEW grtdiff_alter_test.t1v as select * from grtdiff_alter_test.t1;"
   ,""
   ,"[Vv]iew.*t1v.*dropped"
  }
 ,{
    "Drop procedure"
   ,"CREATE PROCEDURE simpleproc (OUT param1 INT) SELECT COUNT(*) INTO param1 FROM t;"
   ,""
   ,"[Rr]outine.*simpleproc.*dropped"
  }
 ,{
    "Create procedure"
   ,""
   ,"CREATE PROCEDURE simpleproc (OUT param1 INT) SELECT COUNT(*) INTO param1 FROM t;"
   ,"[Rr]outine.*simpleproc.*created"
  }
 ,{
    "Drop user"
   ,"CREATE USER U1;"
   ,""
   ,"FIX ME"
  }
 ,{
    "Create user"
   ,""
   ,"CREATE USER U1;"
   ,"FIX ME"
  }
 ,{
    0,
    0,
    0,
    0
  }
};
#endif

#if 0

// TODO: to use function from db_helpers.
//------------------------------------------------------------------------------
static int pcre_compile_exec(const char *pattern, const char *str, int *patres, int patresnum)
{
  const char *errptr;
  int erroffs;
  int c;
  pcre *patre= pcre_compile(pattern, PCRE_DOTALL, &errptr, &erroffs, NULL);
  if (!patre)
    throw std::logic_error("error compiling regex "+std::string(errptr));

  c= pcre_exec(patre, NULL, str, strlen(str), 0, 0, patres, patresnum);
  pcre_free(patre);

  return c;
}

//------------------------------------------------------------------------------
TEST_FUNCTION(-4)
{
  int ovector[32];
  
  std::cout << pcre_compile_exec("", "test 1", ovector, sizeof(ovector) / sizeof(int));
}

//------------------------------------------------------------------------------
TEST_FUNCTION(5)
{
  // TODO: add test for table rename
  // NOTE: collate test doesn't produce the proper diff 
  grt::DbObjectMatchAlterOmf omf;

  populate_grt(grtm.get_grt(), NULL);

  DiffSQLGenInterfaceModule *diffsql_module= 
    static_cast<DiffSQLGenInterfaceModule *>(grtm.get_grt()->get_module("MySQLModuleDbMySQL"));
  ensure("DiffSQLGen module initialization", NULL != diffsql_module);

  Mysql_sql_parser mysql_sql_parser;

  std::vector<const TestCase*> testsFailed;

  for (  const TestCase *currentTest = testCases
        ; currentTest && currentTest->originalSQL
        ; ++currentTest 
      )
  {
    const char* org_sql   = currentTest->originalSQL;
    const char* mod_sql   = currentTest->modifiedSQL;
    const char* test_expr = currentTest->testExpression;

    db_mysql_Catalog org_cat= create_empty_catalog_for_import(grtm.get_grt());
    db_mysql_Catalog mod_cat= create_empty_catalog_for_import(grtm.get_grt());

    {
      std::string org_script;
      org_script
        .append("CREATE DATABASE IF NOT EXISTS grtdiff_alter_test /*!40100 DEFAULT CHARACTER SET latin1 */;\n")
        .append(org_sql);
      mysql_sql_parser.parseSqlScriptString(org_cat, org_script);
    }
    {
      std::string mod_script;
      mod_script
        .append("CREATE DATABASE IF NOT EXISTS grtdiff_alter_test /*!40100 DEFAULT CHARACTER SET latin1 */;\n")
        .append(mod_sql);
      mysql_sql_parser.parseSqlScriptString(mod_cat, mod_script);
    }


    DiffChange* alter_change= diff_make(org_cat, mod_cat, &omf);
    //alter_change->dump_log(0);

    // 1. generate alter
    grt::DictValue options(grtm.get_grt());
    options.set("UseFilteredLists", grt::IntValue(0));
    options.set("TemplateFile", 
      grt::StringValue("../../modules/db.mysql/res/reporting/Basic_Text.tpl/basic_text_report.txt.tpl"));

    char buf1[128];
    sprintf(buf1, "%p", alter_change);
    grt::StringValue out_str(
      diffsql_module->generateReport(org_cat, options, std::string(buf1)));
    
    std::cout << std::endl << std::endl;
    std::cout << (currentTest ? currentTest->name : "<unnamed>") << std::endl << out_str.c_str() << std::endl;

    int ovector[32];
    const int checkResult = pcre_compile_exec(test_expr
                                             ,out_str.c_str()
                                             ,ovector
                                             ,sizeof(ovector) / sizeof(int)
                                             );
    
    //std::cout << "CHECK (" << test_expr << "): '" << checkResult << "'\n";
    
    if ( checkResult != 1 )
    {
      if ( currentTest )
      {
         testsFailed.push_back(currentTest);
         std::cout << "Test '" << currentTest->name << "' failed. code=" << checkResult << std::endl;
      }
    }
    else
      std::cout << "Test '" << (currentTest ? currentTest->name : "") << "' passed." << std::endl;
    //ensure("report test check", checkResult == 1);
  } //for (TestCase *test = testCases; test && test->originalSQL; ++test )
  
  std::cout << std::endl << std::endl << "======= Summary =======" << std::endl;
  if ( testsFailed.size() > 0 )
  {
    std::cout << "There were failed tests\n";
    struct Print
    {
      void operator()(const TestCase* tc)
      {
        std::cout << "Test failed: " << tc->name << std::endl;
      }
    };
    std::for_each(testsFailed.begin(), testsFailed.end(), Print());
    //TODO: print failed tests report
  }
  
  ensure("Diff report tests", testsFailed.size() == 0);
}

#endif

END_TESTS