/* 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 #include #include #include #include #define HARNESS 1 #include "all_tests.h" /*** These tests require a running cluster. Some of them require the ndbmemcache.demo_table to exist. If a particular test-id is supplied, run one test verbosely; otherwise run all tests and indicate pass or fail. ***/ char *connect_string; /* exported to tests */ EXTENSION_LOGGER_DESCRIPTOR *logger; Ndb_cluster_connection * connect(const char *); int list_tests(void); int usage(char *); int main(int argc, char *argv[]) { connect_string = NULL; int test_number = -1; char * test_name = 0; int optc; int req_level; int npass = 0, nfail = 0; Ndb_cluster_connection * conn = NULL; QueryPlan *plan = NULL; Ndb *db = NULL; /* Options */ while((optc = getopt(argc, argv, "hlc:t:")) != -1) { switch(optc) { case 'c': connect_string = optarg; break; case 't': test_number = atoi(optarg); if(test_number > 0) test_number -= 1; else test_name = optarg; break; case 'l': return list_tests(); break; case 'h': default: return usage(argv[0]); break; } } /* If a test name was given, find it by number */ if(test_name) { for(int i = 0; all_tests[i].name; i++) { if(! strcmp(test_name, all_tests[i].name)) { test_number = i; break; } } if(test_number == -1) { printf("Test \"%s\" not found.\n", test_name); exit(1); } } /* Determine requirements level for this test */ if(test_number >= 0) req_level = all_tests[test_number].requires; else req_level = REQ_DEMO_TABLE; // highest level ndb_init(); DEBUG_INIT(NULL, 0); if(req_level >= REQ_NDB_CONNECTION) { printf("Connecting to cluster (%s)\n", connect_string); conn = connect(connect_string); db = new Ndb(conn); db->init(4); } if(req_level >= REQ_DEMO_TABLE) { TableSpec spec("ndbmemcache.demo_table", "mkey", "string_value"); spec.cas_column = "cas_value"; spec.math_column = "math_value"; plan = new QueryPlan(db, &spec); } if(test_number >= 0) { /* Run a particular test */ printf("%s\n", all_tests[test_number].name); int r = all_tests[test_number].function(plan, db, 1); //verbose if(r) { printf(" [FAIL] at line %d\n", r); nfail++; } else { printf(" [PASS]\n"); npass++; } } else { /* Run all tests */ for(int i = 0; all_tests[i].name; i++) { if(all_tests[i].enabled) { printf("%-30s", all_tests[i].name); int r = all_tests[i].function(plan, db, 0); // quiet printf(" %s\n", r ? "[FAIL]" : "[PASS]"); if(r) nfail++; else npass++; } } printf("\nTotals: %d pass ... %d fail\n", npass, nfail); } exit((nfail > 0)); } int list_tests() { printf("\n"); printf("No. %-30s %-20s %-10s\n", "Name", "Requires","Enabled"); printf("----------------------------------------------------------------\n"); for(int i = 0; all_tests[i].name; i++) printf("%d %-30s %-20s %-10s\n", i+1, all_tests[i].name, requirements[all_tests[i].requires], all_tests[i].enabled ? "Yes" : "No"); printf("\n"); return 0; } int usage(char *prog) { printf("\n"); printf("usage %s [options]\n", prog); printf("options: \n"); printf(" -c connectstring : specify NDB connect-string\n"); printf(" -t test-id : run a particular test by number or name\n"); printf(" -l : list tests\n"); printf(" -h : help\n"); printf("\n"); return 0; } Ndb_cluster_connection * connect(const char *connectstring) { int conn_retries = 0; Ndb_cluster_connection *c = new Ndb_cluster_connection(connectstring); /* Set name that appears in the cluster log file */ c->set_name("unit_test"); while(1) { conn_retries++; int r = c->connect(2,1,0); if(r == 0) // success break; else if(r == -1) // unrecoverable error return NULL; else if (r == 1) { // recoverable error if(conn_retries == 5) return NULL; else sleep(1); } } int ready_nodes = c->wait_until_ready(5, 5); if(ready_nodes < 0) { printf("Timeout waiting for cluster \"%s\" to become ready (%d).\n", connectstring, ready_nodes); return NULL; } printf("Connected to \"%s\" as node id %d.\n", connectstring, c->node_id()); if(ready_nodes > 0) printf("Only %d storage nodes are ready.\n", ready_nodes); return c; } void delete_row(QueryPlan *plan, Ndb *db, const char * key, int verbose) { char ndbkeybuffer[300]; Operation op(plan, OP_DELETE, ndbkeybuffer); op.clearKeyNullBits(); op.setKeyPart(COL_STORE_KEY, key, strlen(key)); NdbTransaction * tx = op.startTransaction(db); op.deleteTuple(tx); tx->execute(NdbTransaction::Commit); detail(verbose, "delete \"%s\": %d \n", key, tx->RESULT); tx->close(); }