~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzletest.cc

Merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
660
660
    fprintf(stderr, "\n\n");
661
661
  }
662
662
  drizzle_result_free(&res);
663
 
 
664
 
  return;
665
663
}
666
664
 
667
665
 
905
903
      free(i.second);
906
904
  }
907
905
  var_hash.clear();
908
 
  BOOST_FOREACH(vector<st_command*>::reference i, q_lines)
 
906
  BOOST_FOREACH(st_command* i, q_lines)
909
907
    delete i;
910
908
  for (size_t i= 0; i < var_reg.size(); i++)
911
909
  {
919
917
 
920
918
static void cleanup_and_exit(int exit_code)
921
919
{
922
 
  free_used_memory();
923
 
  internal::my_end();
 
920
  if (0) // Olaf: Freeing resources is unnecessary when exiting
 
921
  {
 
922
    free_used_memory(); 
 
923
    internal::my_end();
 
924
  }
924
925
 
925
 
  if (!silent) {
926
 
    switch (exit_code) {
 
926
  if (!silent) 
 
927
  {
 
928
    switch (exit_code) 
 
929
    {
927
930
    case 1:
928
931
      printf("not ok\n");
929
932
      break;
935
938
      break;
936
939
    default:
937
940
      printf("unknown exit code: %d\n", exit_code);
938
 
      assert(0);
 
941
      assert(false);
939
942
    }
940
943
  }
941
944
  exit(exit_code);
1100
1103
{
1101
1104
  va_list args;
1102
1105
  char buff[1024];
1103
 
  size_t len;
1104
 
 
1105
1106
 
1106
1107
  va_start(args, fmt);
1107
 
  len= vsnprintf(buff, sizeof(buff)-1, fmt, args);
 
1108
  size_t len= vsnprintf(buff, sizeof(buff)-1, fmt, args);
1108
1109
  va_end(args);
1109
1110
 
1110
1111
  ds_res.append(buff, len);
1111
1112
  ds_res.append("\n");
1112
 
 
1113
 
  return;
1114
1113
}
1115
1114
 
1116
1115
 
1126
1125
 
1127
1126
static void cat_file(string* ds, const char* filename)
1128
1127
{
1129
 
  int fd;
1130
 
  uint32_t len;
1131
 
  char buff[512];
1132
 
 
1133
 
  if ((fd= internal::my_open(filename, O_RDONLY, MYF(0))) < 0)
 
1128
  int fd= internal::my_open(filename, O_RDONLY, MYF(0));
 
1129
  if (fd < 0)
1134
1130
    die("Failed to open file '%s'", filename);
1135
 
  while((len= internal::my_read(fd, (unsigned char*)&buff,
1136
 
                      sizeof(buff), MYF(0))) > 0)
 
1131
  uint32_t len;
 
1132
  char buff[512];
 
1133
 
 
1134
  while((len= internal::my_read(fd, (unsigned char*)&buff, sizeof(buff), MYF(0))) > 0)
1137
1135
  {
1138
1136
    char *p= buff, *start= buff;
1139
1137
    while (p < buff+len)
1168
1166
 
1169
1167
*/
1170
1168
 
1171
 
static int run_command(const char * cmd, string * result)
 
1169
static int run_command(const char* cmd, string& result)
1172
1170
{
1173
 
  assert(result!=NULL);
 
1171
  FILE* res_file= popen(cmd, "r");
 
1172
  if (not res_file)
 
1173
    die("popen(\"%s\", \"r\") failed", cmd);
 
1174
 
1174
1175
  char buf[512]= {0};
1175
 
  FILE *res_file;
1176
 
  int error;
1177
 
 
1178
 
  if (!(res_file= popen(cmd, "r")))
1179
 
    die("popen(\"%s\", \"r\") failed", cmd);
1180
 
 
1181
1176
  while (fgets(buf, sizeof(buf), res_file))
1182
1177
  {
1183
1178
    /* Save the output of this command in the supplied string */
1184
 
    result->append(buf);
 
1179
    result.append(buf);
1185
1180
  }
1186
 
 
1187
 
  error= pclose(res_file);
 
1181
  int error= pclose(res_file);
1188
1182
  return WEXITSTATUS(error);
1189
1183
}
1190
1184
 
1201
1195
 
1202
1196
*/
1203
1197
 
1204
 
static int run_tool(const char *tool_path, string * result, ...)
 
1198
static int run_tool(const char *tool_path, string& result, ...)
1205
1199
{
1206
 
  int ret;
1207
 
  const char* arg;
1208
 
  va_list args;
1209
1200
  string ds_cmdline;
1210
 
 
1211
 
 
1212
1201
  append_os_quoted(&ds_cmdline, tool_path, NULL);
1213
1202
  ds_cmdline.append(" ");
1214
1203
 
 
1204
  va_list args;
1215
1205
  va_start(args, result);
1216
 
 
1217
 
  while ((arg= va_arg(args, char *)))
 
1206
  while (const char* arg= va_arg(args, char *))
1218
1207
  {
1219
1208
    /* Options should be os quoted */
1220
1209
    if (strncmp(arg, "--", 2) == 0)
1226
1215
 
1227
1216
  va_end(args);
1228
1217
 
1229
 
  ret= run_command(ds_cmdline.c_str(), result);
1230
 
  return(ret);
 
1218
  return run_command(ds_cmdline.c_str(), result);
1231
1219
}
1232
1220
 
1233
1221
 
1252
1240
 
1253
1241
  /* First try with unified diff */
1254
1242
  if (run_tool("diff",
1255
 
               &ds_tmp, /* Get output from diff in ds_tmp */
 
1243
               ds_tmp, /* Get output from diff in ds_tmp */
1256
1244
               "-u",
1257
1245
               filename1,
1258
1246
               filename2,
1262
1250
 
1263
1251
    /* Fallback to context diff with "diff -c" */
1264
1252
    if (run_tool("diff",
1265
 
                 &ds_tmp, /* Get output from diff in ds_tmp */
 
1253
                 ds_tmp, /* Get output from diff in ds_tmp */
1266
1254
                 "-c",
1267
1255
                 filename1,
1268
1256
                 filename2,
1273
1261
        Fallback to dump both files to result file and inform
1274
1262
        about installing "diff"
1275
1263
      */
1276
 
      ds_tmp.clear();
1277
 
 
1278
 
      ds_tmp.append(
 
1264
      ds_tmp=
1279
1265
                    "\n"
1280
1266
                    "The two files differ but it was not possible to execute 'diff' in\n"
1281
1267
                    "order to show only the difference, tried both 'diff -u' or 'diff -c'.\n"
1282
 
                    "Instead the whole content of the two files was shown for you to diff manually. ;)\n\n"
 
1268
                    "Instead the whole content of the two files was shown for you to diff manually. ;)\n"
 
1269
                    "\n"
1283
1270
                    "To get a better report you should install 'diff' on your system, which you\n"
1284
1271
                    "for example can get from http://www.gnu.org/software/diffutils/diffutils.html\n"
1285
 
                    "\n");
 
1272
                    "\n";
1286
1273
 
1287
1274
      ds_tmp.append(" --- ");
1288
1275
      ds_tmp.append(filename1);
1299
1286
  if (ds)
1300
1287
  {
1301
1288
    /* Add the diff to output */
1302
 
    ds->append(ds_tmp.c_str(), ds_tmp.length());
 
1289
    *ds += ds_tmp;
1303
1290
  }
1304
1291
  else
1305
1292
  {
1309
1296
 
1310
1297
}
1311
1298
 
1312
 
 
1313
 
enum compare_files_result_enum {
 
1299
enum compare_files_result_enum 
 
1300
{
1314
1301
  RESULT_OK= 0,
1315
1302
  RESULT_CONTENT_MISMATCH= 1,
1316
1303
  RESULT_LENGTH_MISMATCH= 2
1333
1320
static int compare_files2(int fd, const char* filename2)
1334
1321
{
1335
1322
  int error= RESULT_OK;
1336
 
  int fd2;
1337
1323
  uint32_t len, len2;
1338
1324
  char buff[512], buff2[512];
1339
1325
  const char *fname= filename2;
1340
1326
  string tmpfile;
1341
1327
 
1342
 
  if ((fd2= internal::my_open(fname, O_RDONLY, MYF(0))) < 0)
 
1328
  int fd2= internal::my_open(fname, O_RDONLY, MYF(0));
 
1329
  if (fd2 < 0)
1343
1330
  {
1344
1331
    internal::my_close(fd, MYF(0));
1345
1332
    if (! opt_testdir.empty())
1431
1418
 
1432
1419
static int string_cmp(string* ds, const char *fname)
1433
1420
{
1434
 
  int error;
1435
 
  int fd;
1436
1421
  char temp_file_path[FN_REFLEN];
1437
1422
 
1438
 
  if ((fd= internal::create_temp_file(temp_file_path, TMPDIR,
1439
 
                            "tmp", MYF(MY_WME))) < 0)
 
1423
  int fd= internal::create_temp_file(temp_file_path, TMPDIR, "tmp", MYF(MY_WME));
 
1424
  if (fd < 0)
1440
1425
    die("Failed to create temporary file for ds");
1441
1426
 
1442
1427
  /* Write ds to temporary file and set file pos to beginning*/
1443
 
  if (internal::my_write(fd, (unsigned char *) ds->c_str(), ds->length(),
1444
 
               MYF(MY_FNABP | MY_WME)) ||
 
1428
  if (internal::my_write(fd, (unsigned char *) ds->c_str(), ds->length(), MYF(MY_FNABP | MY_WME)) ||
1445
1429
      lseek(fd, 0, SEEK_SET) == MY_FILEPOS_ERROR)
1446
1430
  {
1447
1431
    internal::my_close(fd, MYF(0));
1450
1434
    die("Failed to write file '%s'", temp_file_path);
1451
1435
  }
1452
1436
 
1453
 
  error= compare_files2(fd, fname);
 
1437
  int error= compare_files2(fd, fname);
1454
1438
 
1455
1439
  internal::my_close(fd, MYF(0));
1456
1440
  /* Remove the temporary file */
1457
1441
  internal::my_delete(temp_file_path, MYF(0));
1458
1442
 
1459
 
  return(error);
 
1443
  return error;
1460
1444
}
1461
1445
 
1462
1446
 
1476
1460
{
1477
1461
  const char* mess= "Result content mismatch\n";
1478
1462
 
1479
 
 
1480
 
  assert(result_file_name.c_str());
1481
 
 
1482
1463
  if (access(result_file_name.c_str(), F_OK) != 0)
1483
1464
    die("The specified result file does not exist: '%s'", result_file_name.c_str());
1484
1465
 
1485
 
  switch (string_cmp(ds, result_file_name.c_str())) {
 
1466
  switch (string_cmp(ds, result_file_name.c_str())) 
 
1467
  {
1486
1468
  case RESULT_OK:
1487
1469
    break; /* ok */
1488
1470
  case RESULT_LENGTH_MISMATCH:
1501
1483
    if (access(reject_file, W_OK) == 0)
1502
1484
    {
1503
1485
      /* Result file directory is writable, save reject file there */
1504
 
      internal::fn_format(reject_file, result_file_name.c_str(), NULL,
1505
 
                ".reject", MY_REPLACE_EXT);
 
1486
      internal::fn_format(reject_file, result_file_name.c_str(), NULL, ".reject", MY_REPLACE_EXT);
1506
1487
    }
1507
1488
    else
1508
1489
    {
1509
1490
      /* Put reject file in opt_logdir */
1510
 
      internal::fn_format(reject_file, result_file_name.c_str(), opt_logdir.c_str(),
1511
 
                ".reject", MY_REPLACE_DIR | MY_REPLACE_EXT);
 
1491
      internal::fn_format(reject_file, result_file_name.c_str(), opt_logdir.c_str(), ".reject", MY_REPLACE_DIR | MY_REPLACE_EXT);
1512
1492
    }
1513
1493
    str_to_file(reject_file, ds->c_str(), ds->length());
1514
1494
 
1521
1501
  default: /* impossible */
1522
1502
    die("Unknown error code from dyn_string_cmp()");
1523
1503
  }
1524
 
 
1525
 
  return;
1526
1504
}
1527
1505
 
1528
1506
 
1543
1521
 
1544
1522
static void check_require(string* ds, const string &fname)
1545
1523
{
1546
 
 
1547
 
 
1548
1524
  if (string_cmp(ds, fname.c_str()))
1549
1525
  {
1550
1526
    char reason[FN_REFLEN];
1551
1527
    internal::fn_format(reason, fname.c_str(), "", "", MY_REPLACE_EXT | MY_REPLACE_DIR);
1552
1528
    abort_not_supported_test("Test requires: '%s'", reason);
1553
1529
  }
1554
 
  return;
1555
1530
}
1556
1531
 
1557
1532
 
1857
1832
      and assign that string to the $variable
1858
1833
    */
1859
1834
    string result;
1860
 
    uint32_t i;
1861
 
    size_t *lengths;
1862
 
 
1863
 
    lengths= drizzle_row_field_sizes(&res);
1864
 
    for (i= 0; i < drizzle_result_column_count(&res); i++)
 
1835
    size_t* lengths= drizzle_row_field_sizes(&res);
 
1836
    for (uint32_t i= 0; i < drizzle_result_column_count(&res); i++)
1865
1837
    {
1866
1838
      if (row[i])
1867
1839
      {
1905
1877
 
1906
1878
static void var_set_query_get_value(st_command* command, VAR *var)
1907
1879
{
1908
 
  long row_no;
1909
1880
  int col_no= -1;
1910
1881
  drizzle_result_st res;
1911
1882
  drizzle_return_t ret;
1928
1899
                     ',');
1929
1900
 
1930
1901
  /* Convert row number to int */
1931
 
  row_no= atoi(ds_row.c_str());
 
1902
  long row_no= atoi(ds_row.c_str());
1932
1903
  
1933
1904
  istringstream buff(ds_row);
1934
1905
  if ((buff >> row_no).fail())
1936
1907
 
1937
1908
  /* Remove any surrounding "'s from the query - if there is any */
1938
1909
  // (Don't get me started on this)
1939
 
  char * unstripped_query= strdup(ds_query.c_str());
 
1910
  char* unstripped_query= strdup(ds_query.c_str());
1940
1911
  if (strip_surrounding(unstripped_query, '"', '"'))
1941
1912
    die("Mismatched \"'s around query '%s'", ds_query.c_str());
1942
 
  ds_query.clear();
1943
 
  ds_query.append(unstripped_query);
 
1913
  ds_query= unstripped_query;
1944
1914
 
1945
1915
  /* Run the query */
1946
 
  if (drizzle_query(con, &res, ds_query.c_str(), ds_query.length(),
1947
 
                    &ret) == NULL ||
 
1916
  if (drizzle_query(con, &res, ds_query.c_str(), ds_query.length(), &ret) == NULL ||
1948
1917
      ret != DRIZZLE_RETURN_OK)
1949
1918
  {
1950
1919
    if (ret == DRIZZLE_RETURN_ERROR_CODE)
1951
1920
    {
1952
 
      die("Error running query '%s': %d %s", ds_query.c_str(),
1953
 
          drizzle_result_error_code(&res), drizzle_result_error(&res));
 
1921
      die("Error running query '%s': %d %s", ds_query.c_str(), drizzle_result_error_code(&res), drizzle_result_error(&res));
1954
1922
      drizzle_result_free(&res);
1955
1923
    }
1956
1924
    else
1957
1925
    {
1958
 
      die("Error running query '%s': %d %s", ds_query.c_str(), ret,
1959
 
          drizzle_con_error(con));
 
1926
      die("Error running query '%s': %d %s", ds_query.c_str(), ret, drizzle_con_error(con));
1960
1927
    }
1961
1928
  }
1962
1929
  if (drizzle_result_column_count(&res) == 0 ||
1965
1932
 
1966
1933
  {
1967
1934
    /* Find column number from the given column name */
1968
 
    uint32_t i;
1969
1935
    uint32_t num_fields= drizzle_result_column_count(&res);
1970
 
    drizzle_column_st *column;
1971
 
 
1972
 
    for (i= 0; i < num_fields; i++)
 
1936
    for (uint32_t i= 0; i < num_fields; i++)
1973
1937
    {
1974
 
      column= drizzle_column_next(&res);
 
1938
      drizzle_column_st* column= drizzle_column_next(&res);
1975
1939
      if (strcmp(drizzle_column_name(column), ds_col.c_str()) == 0 &&
1976
1940
          strlen(drizzle_column_name(column)) == ds_col.length())
1977
1941
      {
1989
1953
 
1990
1954
  {
1991
1955
    /* Get the value */
1992
 
    drizzle_row_t row;
1993
1956
    long rows= 0;
1994
1957
    const char* value= "No such row";
1995
1958
 
1996
 
    while ((row= drizzle_row_next(&res)))
 
1959
    while (drizzle_row_t row= drizzle_row_next(&res))
1997
1960
    {
1998
1961
      if (++rows == row_no)
1999
1962
      {
2155
2118
    }
2156
2119
    open_file(ds_filename.c_str());
2157
2120
  }
2158
 
 
2159
 
  return;
2160
2121
}
2161
2122
 
2162
2123
 
2401
2362
 
2402
2363
static void do_remove_file(st_command* command)
2403
2364
{
2404
 
  int error;
2405
2365
  string ds_filename;
2406
2366
  const struct command_arg rm_args[] = {
2407
2367
    { "filename", ARG_STRING, true, &ds_filename, "File to delete" }
2412
2372
                     rm_args, sizeof(rm_args)/sizeof(struct command_arg),
2413
2373
                     ' ');
2414
2374
 
2415
 
  error= internal::my_delete(ds_filename.c_str(), MYF(0)) != 0;
 
2375
  int error= internal::my_delete(ds_filename.c_str(), MYF(0)) != 0;
2416
2376
  handle_command_error(command, error);
2417
2377
}
2418
2378
 
2431
2391
 
2432
2392
static void do_copy_file(st_command* command)
2433
2393
{
2434
 
  int error;
2435
2394
  string ds_from_file;
2436
2395
  string ds_to_file;
2437
2396
  const struct command_arg copy_file_args[] = {
2445
2404
                     sizeof(copy_file_args)/sizeof(struct command_arg),
2446
2405
                     ' ');
2447
2406
 
2448
 
  error= (internal::my_copy(ds_from_file.c_str(), ds_to_file.c_str(),
 
2407
  int error= (internal::my_copy(ds_from_file.c_str(), ds_to_file.c_str(),
2449
2408
                  MYF(MY_DONT_OVERWRITE_FILE)) != 0);
2450
2409
  handle_command_error(command, error);
2451
2410
}
2500
2459
 
2501
2460
static void do_file_exist(st_command* command)
2502
2461
{
2503
 
  int error;
2504
2462
  string ds_filename;
2505
2463
  const struct command_arg file_exist_args[] = {
2506
2464
    { "filename", ARG_STRING, true, &ds_filename, "File to check if it exist" }
2512
2470
                     sizeof(file_exist_args)/sizeof(struct command_arg),
2513
2471
                     ' ');
2514
2472
 
2515
 
  error= (access(ds_filename.c_str(), F_OK) != 0);
 
2473
  int error= access(ds_filename.c_str(), F_OK) != 0;
2516
2474
  handle_command_error(command, error);
2517
2475
}
2518
2476
 
2530
2488
static void do_mkdir(st_command* command)
2531
2489
{
2532
2490
  string ds_dirname;
2533
 
  int error;
2534
2491
  const struct command_arg mkdir_args[] = {
2535
2492
    {"dirname", ARG_STRING, true, &ds_dirname, "Directory to create"}
2536
2493
  };
2540
2497
                     mkdir_args, sizeof(mkdir_args)/sizeof(struct command_arg),
2541
2498
                     ' ');
2542
2499
 
2543
 
  error= mkdir(ds_dirname.c_str(), (0777 & internal::my_umask_dir)) != 0;
 
2500
  int error= mkdir(ds_dirname.c_str(), (0777 & internal::my_umask_dir)) != 0;
2544
2501
  handle_command_error(command, error);
2545
2502
}
2546
2503
 
2556
2513
 
2557
2514
static void do_rmdir(st_command* command)
2558
2515
{
2559
 
  int error;
2560
2516
  string ds_dirname;
2561
2517
  const struct command_arg rmdir_args[] = {
2562
2518
    {"dirname", ARG_STRING, true, &ds_dirname, "Directory to remove"}
2567
2523
                     rmdir_args, sizeof(rmdir_args)/sizeof(struct command_arg),
2568
2524
                     ' ');
2569
2525
 
2570
 
  error= rmdir(ds_dirname.c_str()) != 0;
 
2526
  int error= rmdir(ds_dirname.c_str()) != 0;
2571
2527
  handle_command_error(command, error);
2572
2528
}
2573
2529
 
2599
2555
static void read_until_delimiter(string *ds,
2600
2556
                                 string *ds_delimiter)
2601
2557
{
2602
 
  char c;
2603
 
 
2604
2558
  if (ds_delimiter->length() > MAX_DELIMITER_LENGTH)
2605
2559
    die("Max delimiter length(%d) exceeded", MAX_DELIMITER_LENGTH);
2606
2560
 
2607
2561
  /* Read from file until delimiter is found */
2608
2562
  while (1)
2609
2563
  {
2610
 
    c= my_getc(cur_file->file);
 
2564
    char c= my_getc(cur_file->file);
2611
2565
 
2612
2566
    if (c == '\n')
2613
2567
    {
2635
2589
 
2636
2590
    ds->push_back(c);
2637
2591
  }
2638
 
  return;
2639
2592
}
2640
2593
 
2641
2594
 
2667
2620
  }
2668
2621
 
2669
2622
  read_until_delimiter(&ds_content, &ds_delimiter);
2670
 
  str_to_file2(ds_filename.c_str(), ds_content.c_str(),
2671
 
               ds_content.length(), append);
2672
 
  return;
 
2623
  str_to_file2(ds_filename.c_str(), ds_content.c_str(), ds_content.length(), append);
2673
2624
}
2674
2625
 
2675
2626
 
2764
2715
                     ' ');
2765
2716
 
2766
2717
  cat_file(&ds_res, ds_filename.c_str());
2767
 
 
2768
 
  return;
2769
2718
}
2770
2719
 
2771
2720
 
2783
2732
 
2784
2733
static void do_diff_files(st_command* command)
2785
2734
{
2786
 
  int error= 0;
2787
2735
  string ds_filename;
2788
2736
  string ds_filename2;
2789
2737
  const struct command_arg diff_file_args[] = {
2798
2746
                     sizeof(diff_file_args)/sizeof(struct command_arg),
2799
2747
                     ' ');
2800
2748
 
2801
 
  if ((error= compare_files(ds_filename.c_str(), ds_filename2.c_str())))
 
2749
  int error= compare_files(ds_filename.c_str(), ds_filename2.c_str());
 
2750
  if (error)
2802
2751
  {
2803
2752
    /* Compare of the two files failed, append them to output
2804
2753
       so the failure can be analyzed
2812
2761
 
2813
2762
static st_connection * find_connection_by_name(const char *name)
2814
2763
{
2815
 
  st_connection *con;
2816
 
  for (con= g_connections; con < next_con; con++)
 
2764
  for (st_connection* con= g_connections; con < next_con; con++)
2817
2765
  {
2818
 
    if (!strcmp(con->name, name))
2819
 
    {
 
2766
    if (not strcmp(con->name, name))
2820
2767
      return con;
2821
 
    }
2822
2768
  }
2823
 
  return 0; /* Connection not found */
 
2769
  return NULL;
2824
2770
}
2825
2771
 
2826
2772
 
3036
2982
      break;
3037
2983
    usleep(SLAVE_POLL_INTERVAL);
3038
2984
  }
3039
 
  return;
3040
2985
}
3041
2986
 
3042
2987
static void do_sync_with_master2(long offset)