LCOV - code coverage report
Current view: top level - lib/ldb/tools - ldbtest.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 202 245 82.4 %
Date: 2024-02-28 12:06:22 Functions: 9 10 90.0 %

          Line data    Source code
       1             : /* 
       2             :    ldb database library
       3             : 
       4             :    Copyright (C) Andrew Tridgell  2004
       5             : 
       6             :      ** NOTE! The following LGPL license applies to the ldb
       7             :      ** library. This does NOT imply that all of Samba is released
       8             :      ** under the LGPL
       9             :    
      10             :    This library is free software; you can redistribute it and/or
      11             :    modify it under the terms of the GNU Lesser General Public
      12             :    License as published by the Free Software Foundation; either
      13             :    version 3 of the License, or (at your option) any later version.
      14             : 
      15             :    This library is distributed in the hope that it will be useful,
      16             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      18             :    Lesser General Public License for more details.
      19             : 
      20             :    You should have received a copy of the GNU Lesser General Public
      21             :    License along with this library; if not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : /*
      25             :  *  Name: ldb
      26             :  *
      27             :  *  Component: ldbtest
      28             :  *
      29             :  *  Description: utility to test ldb
      30             :  *
      31             :  *  Author: Andrew Tridgell
      32             :  */
      33             : 
      34             : #include "replace.h"
      35             : #include "system/filesys.h"
      36             : #include "system/time.h"
      37             : #include "ldb.h"
      38             : #include "tools/cmdline.h"
      39             : 
      40             : static struct timespec tp1,tp2;
      41             : static struct ldb_cmdline *options;
      42             : 
      43           4 : static void _start_timer(void)
      44             : {
      45           4 :         if (clock_gettime(CUSTOM_CLOCK_MONOTONIC, &tp1) != 0) {
      46           0 :                 clock_gettime(CLOCK_REALTIME, &tp1);
      47             :         }
      48           4 : }
      49             : 
      50           4 : static double _end_timer(void)
      51             : {
      52           4 :         if (clock_gettime(CUSTOM_CLOCK_MONOTONIC, &tp2) != 0) {
      53           0 :                 clock_gettime(CLOCK_REALTIME, &tp2);
      54             :         }
      55           6 :         return((tp2.tv_sec - tp1.tv_sec) + 
      56           4 :                (tp2.tv_nsec - tp1.tv_nsec)*1.0e-9);
      57             : }
      58             : 
      59           4 : static void add_records(struct ldb_context *ldb,
      60             :                         struct ldb_dn *basedn,
      61             :                         unsigned int count)
      62             : {
      63           4 :         struct ldb_message msg = {0};
      64           2 :         unsigned int i;
      65             : 
      66             : #if 0
      67             :         if (ldb_lock(ldb, "transaction") != 0) {
      68             :                 printf("transaction lock failed\n");
      69             :                 exit(LDB_ERR_OPERATIONS_ERROR);
      70             :         }
      71             : #endif
      72         404 :         for (i=0;i<count;i++) {
      73         200 :                 struct ldb_message_element el[6];
      74         200 :                 struct ldb_val vals[6][1];
      75         200 :                 char *name;
      76         400 :                 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
      77             : 
      78         400 :                 name = talloc_asprintf(tmp_ctx, "Test%d", i);
      79             : 
      80         400 :                 msg.dn = ldb_dn_copy(tmp_ctx, basedn);
      81         400 :                 ldb_dn_add_child_fmt(msg.dn, "cn=%s", name);
      82         400 :                 msg.num_elements = 6;
      83         400 :                 msg.elements = el;
      84             : 
      85         400 :                 el[0].flags = 0;
      86         400 :                 el[0].name = talloc_strdup(tmp_ctx, "cn");
      87         400 :                 el[0].num_values = 1;
      88         400 :                 el[0].values = vals[0];
      89         400 :                 vals[0][0].data = (uint8_t *)name;
      90         400 :                 vals[0][0].length = strlen(name);
      91             : 
      92         400 :                 el[1].flags = 0;
      93         400 :                 el[1].name = "title";
      94         400 :                 el[1].num_values = 1;
      95         400 :                 el[1].values = vals[1];
      96         400 :                 vals[1][0].data = (uint8_t *)talloc_asprintf(tmp_ctx, "The title of %s", name);
      97         400 :                 vals[1][0].length = strlen((char *)vals[1][0].data);
      98             : 
      99         400 :                 el[2].flags = 0;
     100         400 :                 el[2].name = talloc_strdup(tmp_ctx, "uid");
     101         400 :                 el[2].num_values = 1;
     102         400 :                 el[2].values = vals[2];
     103         400 :                 vals[2][0].data = (uint8_t *)ldb_casefold(ldb, tmp_ctx, name, strlen(name));
     104         400 :                 vals[2][0].length = strlen((char *)vals[2][0].data);
     105             : 
     106         400 :                 el[3].flags = 0;
     107         400 :                 el[3].name = talloc_strdup(tmp_ctx, "mail");
     108         400 :                 el[3].num_values = 1;
     109         400 :                 el[3].values = vals[3];
     110         400 :                 vals[3][0].data = (uint8_t *)talloc_asprintf(tmp_ctx, "%s@example.com", name);
     111         400 :                 vals[3][0].length = strlen((char *)vals[3][0].data);
     112             : 
     113         400 :                 el[4].flags = 0;
     114         400 :                 el[4].name = talloc_strdup(tmp_ctx, "objectClass");
     115         400 :                 el[4].num_values = 1;
     116         400 :                 el[4].values = vals[4];
     117         400 :                 vals[4][0].data = (uint8_t *)talloc_strdup(tmp_ctx, "OpenLDAPperson");
     118         400 :                 vals[4][0].length = strlen((char *)vals[4][0].data);
     119             : 
     120         400 :                 el[5].flags = 0;
     121         400 :                 el[5].name = talloc_strdup(tmp_ctx, "sn");
     122         400 :                 el[5].num_values = 1;
     123         400 :                 el[5].values = vals[5];
     124         400 :                 vals[5][0].data = (uint8_t *)name;
     125         400 :                 vals[5][0].length = strlen((char *)vals[5][0].data);
     126             : 
     127         400 :                 ldb_delete(ldb, msg.dn);
     128             : 
     129         400 :                 if (ldb_add(ldb, &msg) != LDB_SUCCESS) {
     130           0 :                         printf("Add of %s failed - %s\n", name, ldb_errstring(ldb));
     131           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
     132             :                 }
     133             : 
     134         400 :                 printf("adding uid %s\r", name);
     135         400 :                 fflush(stdout);
     136             : 
     137         400 :                 talloc_free(tmp_ctx);
     138             :         }
     139             : #if 0
     140             :         if (ldb_unlock(ldb, "transaction") != 0) {
     141             :                 printf("transaction unlock failed\n");
     142             :                 exit(LDB_ERR_OPERATIONS_ERROR);
     143             :         }
     144             : #endif
     145           4 :         printf("\n");
     146           4 : }
     147             : 
     148           4 : static void modify_records(struct ldb_context *ldb,
     149             :                            struct ldb_dn *basedn,
     150             :                            unsigned int count)
     151             : {
     152           4 :         struct ldb_message msg = {0};
     153           2 :         unsigned int i;
     154             : 
     155         404 :         for (i=0;i<count;i++) {
     156         200 :                 struct ldb_message_element el[3];
     157         200 :                 struct ldb_val vals[3];
     158         200 :                 char *name;
     159         400 :                 TALLOC_CTX *tmp_ctx = talloc_new(ldb);
     160             :                 
     161         400 :                 name = talloc_asprintf(tmp_ctx, "Test%d", i);
     162         400 :                 msg.dn = ldb_dn_copy(tmp_ctx, basedn);
     163         400 :                 ldb_dn_add_child_fmt(msg.dn, "cn=%s", name);
     164             : 
     165         400 :                 msg.num_elements = 3;
     166         400 :                 msg.elements = el;
     167             : 
     168         400 :                 el[0].flags = LDB_FLAG_MOD_DELETE;
     169         400 :                 el[0].name = talloc_strdup(tmp_ctx, "mail");
     170         400 :                 el[0].num_values = 0;
     171             : 
     172         400 :                 el[1].flags = LDB_FLAG_MOD_ADD;
     173         400 :                 el[1].name = talloc_strdup(tmp_ctx, "mail");
     174         400 :                 el[1].num_values = 1;
     175         400 :                 el[1].values = &vals[1];
     176         400 :                 vals[1].data = (uint8_t *)talloc_asprintf(tmp_ctx, "%s@other.example.com", name);
     177         400 :                 vals[1].length = strlen((char *)vals[1].data);
     178             : 
     179         400 :                 el[2].flags = LDB_FLAG_MOD_REPLACE;
     180         400 :                 el[2].name = talloc_strdup(tmp_ctx, "mail");
     181         400 :                 el[2].num_values = 1;
     182         400 :                 el[2].values = &vals[2];
     183         400 :                 vals[2].data = (uint8_t *)talloc_asprintf(tmp_ctx, "%s@other2.example.com", name);
     184         400 :                 vals[2].length = strlen((char *)vals[2].data);
     185             : 
     186         400 :                 if (ldb_modify(ldb, &msg) != LDB_SUCCESS) {
     187           0 :                         printf("Modify of %s failed - %s\n", name, ldb_errstring(ldb));
     188           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
     189             :                 }
     190             : 
     191         400 :                 printf("Modifying uid %s\r", name);
     192         400 :                 fflush(stdout);
     193             : 
     194         400 :                 talloc_free(tmp_ctx);
     195             :         }
     196             : 
     197           4 :         printf("\n");
     198           4 : }
     199             : 
     200             : 
     201           4 : static void delete_records(struct ldb_context *ldb,
     202             :                            struct ldb_dn *basedn,
     203             :                            unsigned int count)
     204             : {
     205           2 :         unsigned int i;
     206             : 
     207         404 :         for (i=0;i<count;i++) {
     208         200 :                 struct ldb_dn *dn;
     209         400 :                 char *name = talloc_asprintf(ldb, "Test%d", i);
     210         400 :                 dn = ldb_dn_copy(name, basedn);
     211         400 :                 ldb_dn_add_child_fmt(dn, "cn=%s", name);
     212             : 
     213         400 :                 printf("Deleting uid Test%d\r", i);
     214         400 :                 fflush(stdout);
     215             : 
     216         400 :                 if (ldb_delete(ldb, dn) != LDB_SUCCESS) {
     217           0 :                         printf("Delete of %s failed - %s\n", ldb_dn_get_linearized(dn), ldb_errstring(ldb));
     218           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
     219             :                 }
     220         400 :                 talloc_free(name);
     221             :         }
     222             : 
     223           4 :         printf("\n");
     224           4 : }
     225             : 
     226           4 : static void search_uid(struct ldb_context *ldb, struct ldb_dn *basedn,
     227             :                        unsigned int nrecords, unsigned int nsearches)
     228             : {
     229           2 :         unsigned int i;
     230             : 
     231        1024 :         for (i=0;i<nsearches;i++) {
     232        1020 :                 int uid = (i * 700 + 17) % (nrecords * 2);
     233         510 :                 char *expr;
     234        1020 :                 struct ldb_result *res = NULL;
     235         510 :                 int ret;
     236             : 
     237        1020 :                 expr = talloc_asprintf(ldb, "(uid=TEST%d)", uid);
     238        1020 :                 ret = ldb_search(ldb, ldb, &res, basedn, LDB_SCOPE_SUBTREE, NULL, "%s", expr);
     239             : 
     240        1020 :                 if (ret != LDB_SUCCESS || (uid < nrecords && res->count != 1)) {
     241           0 :                         printf("Failed to find %s - %s\n", expr, ldb_errstring(ldb));
     242           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
     243             :                 }
     244             : 
     245        1020 :                 if (uid >= nrecords && res->count > 0) {
     246           0 :                         printf("Found %s !? - %d\n", expr, ret);
     247           0 :                         exit(LDB_ERR_OPERATIONS_ERROR);
     248             :                 }
     249             : 
     250        1020 :                 printf("Testing uid %d/%d - %d  \r", i, uid, res->count);
     251        1020 :                 fflush(stdout);
     252             : 
     253        1020 :                 talloc_free(res);
     254        1020 :                 talloc_free(expr);
     255             :         }
     256             : 
     257           4 :         printf("\n");
     258           4 : }
     259             : 
     260           4 : static void start_test(struct ldb_context *ldb, unsigned int nrecords,
     261             :                        unsigned int nsearches)
     262             : {
     263           2 :         struct ldb_dn *basedn;
     264             : 
     265           4 :         basedn = ldb_dn_new(ldb, ldb, options->basedn);
     266           4 :         if ( ! ldb_dn_validate(basedn)) {
     267           0 :                 printf("Invalid base DN format\n");
     268           0 :                 exit(LDB_ERR_INVALID_DN_SYNTAX);
     269             :         }
     270             : 
     271           4 :         printf("Adding %d records\n", nrecords);
     272           4 :         add_records(ldb, basedn, nrecords);
     273             : 
     274           4 :         printf("Starting search on uid\n");
     275           4 :         _start_timer();
     276           4 :         search_uid(ldb, basedn, nrecords, nsearches);
     277           4 :         printf("uid search took %.2f seconds\n", _end_timer());
     278             : 
     279           4 :         printf("Modifying records\n");
     280           4 :         modify_records(ldb, basedn, nrecords);
     281             : 
     282           4 :         printf("Deleting records\n");
     283           4 :         delete_records(ldb, basedn, nrecords);
     284           4 : }
     285             : 
     286             : 
     287             : /*
     288             :       2) Store an @indexlist record
     289             : 
     290             :       3) Store a record that contains fields that should be index according
     291             : to @index
     292             : 
     293             :       4) disconnection from database
     294             : 
     295             :       5) connect to same database
     296             : 
     297             :       6) search for record added in step 3 using a search key that should
     298             : be indexed
     299             : */
     300           4 : static void start_test_index(struct ldb_context **ldb)
     301             : {
     302           2 :         struct ldb_message *msg;
     303           4 :         struct ldb_result *res = NULL;
     304           2 :         struct ldb_dn *indexlist;
     305           2 :         struct ldb_dn *basedn;
     306           2 :         int ret;
     307           4 :         unsigned int flags = 0;
     308           2 :         const char *specials;
     309             : 
     310           4 :         specials = getenv("LDB_SPECIALS");
     311           6 :         if (specials && atoi(specials) == 0) {
     312           0 :                 printf("LDB_SPECIALS disabled - skipping index test\n");
     313           0 :                 return;
     314             :         }
     315             : 
     316           4 :         if (options->nosync) {
     317           0 :                 flags |= LDB_FLG_NOSYNC;
     318             :         }
     319             : 
     320           4 :         printf("Starting index test\n");
     321             : 
     322           4 :         indexlist = ldb_dn_new(*ldb, *ldb, "@INDEXLIST");
     323             : 
     324           4 :         ldb_delete(*ldb, indexlist);
     325             : 
     326           4 :         msg = ldb_msg_new(NULL);
     327           4 :         if (msg == NULL) {
     328           0 :                 printf("ldb_msg_new failed\n");
     329           0 :                 exit(LDB_ERR_OPERATIONS_ERROR);
     330             :         }
     331             : 
     332           4 :         msg->dn = indexlist;
     333           4 :         ldb_msg_add_string(msg, "@IDXATTR", strdup("uid"));
     334             : 
     335           4 :         if (ldb_add(*ldb, msg) != 0) {
     336           0 :                 printf("Add of %s failed - %s\n", ldb_dn_get_linearized(msg->dn), ldb_errstring(*ldb));
     337           0 :                 exit(LDB_ERR_OPERATIONS_ERROR);
     338             :         }
     339             : 
     340           4 :         basedn = ldb_dn_new(*ldb, *ldb, options->basedn);
     341             : 
     342           4 :         memset(msg, 0, sizeof(*msg));
     343           4 :         msg->dn = ldb_dn_copy(msg, basedn);
     344           4 :         ldb_dn_add_child_fmt(msg->dn, "cn=test");
     345           4 :         ldb_msg_add_string(msg, "cn", strdup("test"));
     346           4 :         ldb_msg_add_string(msg, "sn", strdup("test"));
     347           4 :         ldb_msg_add_string(msg, "uid", strdup("test"));
     348           4 :         ldb_msg_add_string(msg, "objectClass", strdup("OpenLDAPperson"));
     349             : 
     350           4 :         if (ldb_add(*ldb, msg) != LDB_SUCCESS) {
     351           0 :                 printf("Add of %s failed - %s\n", ldb_dn_get_linearized(msg->dn), ldb_errstring(*ldb));
     352           0 :                 exit(LDB_ERR_OPERATIONS_ERROR);
     353             :         }
     354             : 
     355           4 :         if (talloc_free(*ldb) != 0) {
     356           0 :                 printf("failed to free/close ldb database");
     357           0 :                 exit(LDB_ERR_OPERATIONS_ERROR);
     358             :         }
     359             : 
     360           4 :         (*ldb) = ldb_init(options, NULL);
     361             : 
     362           4 :         ret = ldb_connect(*ldb, options->url, flags, NULL);
     363           4 :         if (ret != LDB_SUCCESS) {
     364           0 :                 printf("failed to connect to %s\n", options->url);
     365           0 :                 exit(LDB_ERR_OPERATIONS_ERROR);
     366             :         }
     367             : 
     368           4 :         basedn = ldb_dn_new(*ldb, *ldb, options->basedn);
     369           4 :         msg->dn = basedn;
     370           4 :         ldb_dn_add_child_fmt(msg->dn, "cn=test");
     371             : 
     372           4 :         ret = ldb_search(*ldb, *ldb, &res, basedn, LDB_SCOPE_SUBTREE, NULL, "uid=test");
     373           4 :         if (ret != LDB_SUCCESS) { 
     374           0 :                 printf("Search with (uid=test) filter failed!\n");
     375           0 :                 exit(LDB_ERR_OPERATIONS_ERROR);
     376             :         }
     377           4 :         if(res->count != 1) {
     378           0 :                 printf("Should have found 1 record - found %d\n", res->count);
     379           0 :                 exit(LDB_ERR_OPERATIONS_ERROR);
     380             :         }
     381             : 
     382           4 :         indexlist = ldb_dn_new(*ldb, *ldb, "@INDEXLIST");
     383             : 
     384           8 :         if (ldb_delete(*ldb, msg->dn) != 0 ||
     385           4 :             ldb_delete(*ldb, indexlist) != 0) {
     386           0 :                 printf("cleanup failed - %s\n", ldb_errstring(*ldb));
     387           0 :                 exit(LDB_ERR_OPERATIONS_ERROR);
     388             :         }
     389             : 
     390           4 :         printf("Finished index test\n");
     391             : }
     392             : 
     393             : 
     394           0 : static void usage(struct ldb_context *ldb)
     395             : {
     396           0 :         printf("Usage: ldbtest <options>\n");
     397           0 :         printf("Options:\n");
     398           0 :         printf("  -H ldb_url       choose the database (or $LDB_URL)\n");
     399           0 :         printf("  --num-records  nrecords      database size to use\n");
     400           0 :         printf("  --num-searches nsearches     number of searches to do\n");
     401           0 :         printf("\n");
     402           0 :         printf("tests ldb API\n\n");
     403           0 :         exit(LDB_ERR_OPERATIONS_ERROR);
     404             : }
     405             : 
     406           4 : int main(int argc, const char **argv)
     407             : {
     408           4 :         TALLOC_CTX *mem_ctx = talloc_new(NULL);
     409           2 :         struct ldb_context *ldb;
     410             : 
     411           4 :         ldb = ldb_init(mem_ctx, NULL);
     412           4 :         if (ldb == NULL) {
     413           0 :                 return LDB_ERR_OPERATIONS_ERROR;
     414             :         }
     415             : 
     416           4 :         options = ldb_cmdline_process(ldb, argc, argv, usage);
     417             : 
     418           4 :         talloc_steal(mem_ctx, options);
     419             : 
     420           4 :         if (options->basedn == NULL) {
     421           4 :                 options->basedn = "ou=Ldb Test,ou=People,o=University of Michigan,c=TEST";
     422             :         }
     423             : 
     424           4 :         srandom(1);
     425             : 
     426           6 :         printf("Testing with num-records=%d and num-searches=%d\n", 
     427           4 :                options->num_records, options->num_searches);
     428             : 
     429           4 :         start_test(ldb,
     430           4 :                    (unsigned int) options->num_records,
     431           4 :                    (unsigned int) options->num_searches);
     432             : 
     433           4 :         start_test_index(&ldb);
     434             : 
     435           4 :         talloc_free(mem_ctx);
     436             : 
     437           4 :         return LDB_SUCCESS;
     438             : }

Generated by: LCOV version 1.14