Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  nbdb_process_test.c

  Sprache: C
 

/*++
/* NAME
/* nbdb_process_test 1t
/* SUMMARY
/* nbdb_process unit test
/* SYNOPSIS
/* ./nbdb_process_test
/* DESCRIPTION
/* nbdb_process_test runs and logs each configured test, reports if
/* a test is a PASS or FAIL, and returns an exit status of zero if
/* all tests are a PASS.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* porcupine.org
/*--*/


 /*
  * System library.
  */

#include <sys_defs.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>

 /*
  * Utility library.
  */

#include <dict_cdb.h>
#include <dict_lmdb.h>
#include <msg.h>
#include <msg_vstream.h>
#include <mock_dict.h>
#include <mock_stat.h>
#include <stringops.h>
#include <vstream.h>
#include <vstring.h>

 /*
  * Global library.
  */

#include <allowed_prefix.h>
#include <nbdb_util.h>
#include <mail_params.h>
#include <msg_capture.h>

 /*
  * Testing library.
  */

#include <mock_spawn_command.h>
#include <mock_stat.h>
#include <mock_open_as.h>

 /*
  * Application-specific.
  */

#include <nbdb_index_as.h>
#include <nbdb_safe.h>
#include <nbdb_index_as.h>
#include <nbdb_process.h>

#define STR(x) vstring_str(x)
#define LEN(x) VSTRING_LEN(x)

 /*
  * Scaffolding for static parameter dependencies.
  */

char   *var_command_dir = DEF_COMMAND_DIR;
char   *var_export_environ = "TZ MAIL_CONFIG LANG";
char   *var_servname = "nbdb_reindexd";
char   *var_db_type = DICT_TYPE_CDB;
char   *var_cache_db_type = DICT_TYPE_LMDB;
char   *var_nbdb_cust_map = DEF_NBDB_CUST_MAP;

 /*
  * Test-dependent configuration parameters.
  */

bool    var_nbdb_enable = 0;

char   *var_nbdb_allow_root_pfxs = DEF_NBDB_ALLOW_ROOT_PFXS;
char   *var_nbdb_allow_user_pfxs = DEF_NBDB_ALLOW_USER_PFXS;

ALLOWED_PREFIX *parsed_allow_root_pfxs;
ALLOWED_PREFIX *parsed_allow_user_pfxs;

 /*
  * Test structure. TODO(wietse) readability problem: there are many test
  * inputs, their values have a lot of overlap, and the tests data are far
  * away from the code that uses it. For readability sake, consider using
  * dedicated test-case functions with test data in local variables.
  */

typedef struct TEST_CASE {
    const char *label;
    int     (*action) (const struct TEST_CASE *);

    /*
     * Mock dependencies.
     */

    MOCK_STAT_REQ mock_stat_source;
    MOCK_STAT_REQ mock_stat_leg_idx;
    MOCK_STAT_REQ mock_stat_parent;
    MOCK_STAT_REQ mock_stat_new_idx;
    MOCK_OPEN_AS_REQ mock_open;
    MOCK_SPAWN_CMD_REQ mock_spawn;

    /*
     * nbdb_process() inputs and expected outputs.
     */

    struct {
 const char *in_new_type;
 const char *in_source_path;
 int     want_status;
 const char *want_why;
 const char *want_msg;
    }       process;

    /*
     * Configuration parameter settings.
     */

    struct {
 const char *migr_level;
 const char *allow_root_pfxs;
 const char *allow_user_pfxs;
    }       params;
} TEST_CASE;

#define PASS    (0)
#define FAIL    (1)

/* test_nbdb_process */

static int test_nbdb_process(const TEST_CASE *tp)
{
    MSG_CAPTURE *capture;
    const char *got_msg;
    int     got_status;
    VSTRING *got_why;
    int     pass = 1;

    nbdb_util_init(tp->params.migr_level);
    setup_mock_cdb("{{x = x}}");
    setup_mock_lmdb("{{x = x}}");
    if (nbdb_level >= NBDB_LEV_CODE_REINDEX) {
 var_nbdb_allow_root_pfxs = (char *) tp->params.allow_root_pfxs;
 var_nbdb_allow_user_pfxs = (char *) tp->params.allow_user_pfxs;

 parsed_allow_root_pfxs = allowed_prefix_create(var_nbdb_allow_root_pfxs);
 parsed_allow_user_pfxs = allowed_prefix_create(var_nbdb_allow_user_pfxs);

 setup_mock_stat(&tp->mock_stat_source);
 setup_mock_stat(&tp->mock_stat_leg_idx);
 setup_mock_stat(&tp->mock_stat_parent);
 setup_mock_stat(&tp->mock_stat_new_idx);
 setup_mock_vstream_fopen_as(&tp->mock_open);
 setup_mock_spawn_command(&tp->mock_spawn);
    }
    capture = msg_capt_create(100);
    got_why = vstring_alloc(100);

    msg_capt_start(capture);
    got_status =
 nbdb_process(tp->process.in_new_type, tp->process.in_source_path,
       got_why);
    msg_capt_stop(capture);
    got_msg = msg_capt_expose(capture);

    if (tp->process.want_why == 0 && LEN(got_why) > 0) {
 msg_warn("got unexpected reason '%s', want (none)", STR(got_why));
 pass = 0;
    }
    if (tp->process.want_msg == 0 && *got_msg != 0) {
 msg_warn("got unexpected message '%s', want (none)", got_msg);
 pass = 0;
    }
    if (tp->process.want_msg && strstr(got_msg, tp->process.want_msg) == 0) {
 msg_warn("got unexpected message '%s', want '%s'",
   got_msg, tp->process.want_msg);
 pass = 0;
    }
    if (got_status != tp->process.want_status) {
 msg_warn("got status '%d', want '%d'", got_status,
   tp->process.want_status);
 pass = 0;
    } else if (got_status != 0
        && strstr(STR(got_why), tp->process.want_why) == 0) {
 msg_warn("got reason '%s', want '%s'", STR(got_why),
   tp->process.want_why);
 pass = 0;
    }
    vstring_free(got_why);
    msg_capt_free(capture);
    if (nbdb_level >= NBDB_LEV_CODE_REINDEX) {
 allowed_prefix_free(parsed_allow_root_pfxs);
 allowed_prefix_free(parsed_allow_user_pfxs);
    }
    return (pass ? PASS : FAIL);
}

 /*
  * The list of test cases. If you want to figure out what the tests do, the
  * data below shows their recipe.
  */

static const TEST_CASE test_cases[] = {

    {.label = "normal_completion",
 .action = test_nbdb_process,
 .mock_stat_source = {
     .want_path = "/path/to/file",
     .out_errno = 0,
     .out_st = {.st_mode = S_IRWXU,.st_uid = 0,.st_gid = 0,},
 },
 .mock_stat_leg_idx = {
     .want_path = "/path/to/file.db",
     .out_errno = 0,
     .out_st = {.st_mode = S_IRWXU,.st_uid = 0,.st_gid = 0,},
 },
 .mock_stat_parent = {
     .want_path = "/path/to",
     .out_errno = 0,
     .out_st = {.st_mode = S_IRWXU,.st_uid = 0,.st_gid = 0,},
 },
 .mock_stat_new_idx = {
     .want_path = "/path/to/file.cdb",
     .out_errno = ENOENT,
 },
 .mock_open = {
     .want_path = "/path/to/file",
     .want_uid = 0,
     .want_gid = 0,
     .out_errno = 0,
     .out_data = "foo bar\nfoo :bar",
 },
 .mock_spawn = {
     .want_args = {
  .argv = (char *[]) {DEF_COMMAND_DIR "/postmap""cdb:/path/to/file"0,},
  .uid = 0,
  .gid = 0,
  .export = (char *[]) {"TZ""MAIL_CONFIG""LANG"0,},
  .time_limit = 100,
     },
     .out_status = 0,
     .out_text = 0,
 },
 .params = {
     .allow_root_pfxs = "/path/to",
     .allow_user_pfxs = "/home/foo",
     .migr_level = "enable-reindex",
 },
 .process = {
     .in_new_type = "hash",
     .in_source_path = "/path/to/file",
     .want_status = NBDB_STAT_OK,
     .want_why = 0,
     .want_msg = "successfully executed",
 },
    },

    {.label = "respects_migr_level_disable",
 .action = test_nbdb_process,
 .params = {
     .migr_level = "disable",
 },
 .process = {
     .want_status = NBDB_STAT_ERROR,
     .want_why = "service is disabled",
 },
    },

    {.label = "propagates_nbdb_index_as_error",
 .action = test_nbdb_process,
 .mock_stat_source = {
     .want_path = "/path/to/file",
     .out_errno = 0,
     .out_st = {.st_mode = S_IRWXU,.st_uid = 0,.st_gid = 0,},
 },
 .mock_stat_leg_idx = {
     .want_path = "/path/to/file.db",
     .out_errno = 0,
     .out_st = {.st_mode = S_IRWXU,.st_uid = 0,.st_gid = 0,},
 },
 .mock_stat_parent = {
     .want_path = "/path/to",
     .out_errno = 0,
     .out_st = {.st_mode = S_IRWXU,.st_uid = 0,.st_gid = 0,},
 },
 .mock_stat_new_idx = {
     .want_path = "/path/to/file.cdb",
     .out_errno = ENOENT,
 },
 .mock_open = {
     .want_path = "/path/to/file",
     .want_uid = 0,
     .want_gid = 0,
     .out_errno = 0,
     .out_data = "foo bar\nfoo :bar",
 },
 .mock_spawn = {
     .want_args = {
  .argv = (char *[]) {DEF_COMMAND_DIR "/postmap""cdb:/path/to/file"0,},
  .uid = 0,
  .gid = 0,
  .export = (char *[]) {"TZ""MAIL_CONFIG""LANG"0,},
  .time_limit = 100,
     },
     .out_status = NBDB_STAT_ERROR,
     .out_text = "sorry, I cannot do that",
 },
 .params = {
     .allow_root_pfxs = "/path/to",
     .allow_user_pfxs = "/home/foo",
     .migr_level = "enable-reindex",
 },
 .process = {
     .in_new_type = "hash",
     .in_source_path = "/path/to/file",
     .want_status = NBDB_STAT_ERROR,
     .want_why = "cannot do that",
 },
    },

    {.label = "propagates_nbdb_safe_to_index_error",
 .action = test_nbdb_process,
 .mock_stat_source = {
     .want_path = "/path/to/file",
     .out_errno = 0,
     .out_st = {.st_mode = S_IRWXU,.st_uid = 0,.st_gid = 0,},
 },
 .mock_stat_leg_idx = {
     .want_path = "/path/to/file.db",
     .out_errno = 0,
     .out_st = {.st_mode = S_IRWXU,.st_uid = 0,.st_gid = 0,},
 },
 .mock_stat_parent = {
     .want_path = "/path/to",
     .out_errno = 0,
     .out_st = {.st_mode = S_IWGRP,.st_uid = 0,.st_gid = 0,},
 },
 .mock_stat_new_idx = {
     .want_path = "/path/to/file.cdb",
     .out_errno = ENOENT,
 },
 .mock_open = {
     .want_path = "/path/to/file",
     .want_uid = 0,
     .want_gid = 0,
     .out_errno = 0,
     .out_data = "foo bar\nfoo :bar",
 },
 .params = {
     .allow_root_pfxs = "/path/to",
     .allow_user_pfxs = "/home/foo",
     .migr_level = "enable-reindex",
 },
 .process = {
     .in_new_type = "hash",
     .in_source_path = "/path/to/file",
     .want_status = NBDB_STAT_ERROR,
     .want_why = "owned or writable by other user",
 },
    },

    {.label = "propagates_nbdb_sniffer_error",
 .action = test_nbdb_process,
 .mock_stat_source = {
     .want_path = "/path/to/file",
     .out_errno = 0,
     .out_st = {.st_mode = S_IRWXU,.st_uid = 0,.st_gid = 0,},
 },
 .mock_stat_leg_idx = {
     .want_path = "/path/to/file.db",
     .out_errno = 0,
     .out_st = {.st_mode = S_IRWXU,.st_uid = 0,.st_gid = 0,},
 },
 .mock_stat_parent = {
     .want_path = "/path/to",
     .out_errno = 0,
     .out_st = {.st_mode = S_IRWXU,.st_uid = 0,.st_gid = 0,},
 },
 .mock_stat_new_idx = {
     .want_path = "/path/to/file.cdb",
     .out_errno = ENOENT,
 },
 .mock_open = {
     .want_path = "/path/to/file",
     .want_uid = 0,
     .want_gid = 0,
     .out_errno = EACCES,
     .out_data = 0,
 },
 .params = {
     .allow_root_pfxs = "/path/to",
     .allow_user_pfxs = "/home/foo",
     .migr_level = "enable-reindex",
 },
 .process = {
     .in_new_type = "hash",
     .in_source_path = "/path/to/file",
     .want_status = NBDB_STAT_ERROR,
     .want_why = "open lookup table source file /path/to/file",
 },
    },

    /*
     * Pathname prefix safety is enforced by nbdb_safe_to_index_as_xxx but it
     * is important enough to have its own end-to-end test.
     */

    {.label = "respects_allow_root_prefix",
 .action = test_nbdb_process,
 .mock_stat_source = {
     .want_path = "/path/to/file",
     .out_errno = 0,
     .out_st = {
  .st_mode = S_IRWXU,.st_uid = 1,.st_gid = 0,
     },
 },
 .mock_stat_leg_idx = {
     .want_path = "/path/to/file.db",
     .out_errno = 0,
     .out_st = {
  .st_mode = S_IRWXU,.st_uid = 1,.st_gid = 0,
     },
 },
 .mock_stat_parent = {
     .want_path = "/path/to",
     .out_errno = 0,
     .out_st = {
  .st_mode = S_IRWXU,.st_uid = 1,.st_gid = 0,
     },
 },
 .mock_stat_new_idx = {
     .want_path = "/path/to/file.cdb",
     .out_errno = ENOENT,
 },
 .mock_open = {
     .want_path = "/path/to/file",
     .want_uid = 1,
     .want_gid = 0,
     .out_errno = 0,
     .out_data = "foo bar\nfoo :bar",
 },
 .params = {
     .allow_root_pfxs = "/other/path",
     .allow_user_pfxs = "/home/foo",
     .migr_level = "enable-reindex",
 },
 .process = {
     .in_new_type = "hash",
     .in_source_path = "/path/to/file",
     .want_status = NBDB_STAT_ERROR,
     .want_why = "could not execute command 'postmap cdb:/path/to/file': table /path/to/file has an unexpected pathname",
 },
    },

    {.label = "normal_completion_non_root_case",
 .action = test_nbdb_process,
 .mock_stat_source = {
     .want_path = "/path/to/file",
     .out_errno = 0,
     .out_st = {.st_mode = S_IRWXU,.st_uid = 1,.st_gid = 0,},
 },
 .mock_stat_leg_idx = {
     .want_path = "/path/to/file.db",
     .out_errno = 0,
     .out_st = {.st_mode = S_IRWXU,.st_uid = 1,.st_gid = 0,},
 },
 .mock_stat_parent = {
     .want_path = "/path/to",
     .out_errno = 0,
     .out_st = {.st_mode = S_IRWXU,.st_uid = 1,.st_gid = 0,},
 },
 .mock_stat_new_idx = {
     .want_path = "/path/to/file.cdb",
     .out_errno = ENOENT,
 },
 .mock_open = {
     .want_path = "/path/to/file",
     .want_uid = 1,
     .want_gid = 0,
     .out_errno = 0,
     .out_data = "foo bar\nfoo :bar",
 },
 .mock_spawn = {
     .want_args = {
  .argv = (char *[]) {DEF_COMMAND_DIR "/postmap""cdb:/path/to/file"0,},
  .uid = 1,
  .gid = 0,
  .export = (char *[]) {"TZ""MAIL_CONFIG""LANG"0,},
  .time_limit = 100,
     },
     .out_status = 0,
     .out_text = 0,
 },
 .params = {
     .allow_root_pfxs = "/somewhere",
     .allow_user_pfxs = "/path/to",
     .migr_level = "enable-reindex",
 },
 .process = {
     .in_new_type = "hash",
     .in_source_path = "/path/to/file",
     .want_status = NBDB_STAT_OK,
     .want_why = 0,
     .want_msg = "successfully executed",
 },
    },

    {.label = "respects_allow_user_prefix",
 .action = test_nbdb_process,
 .mock_stat_source = {
     .want_path = "/path/to/file",
     .out_errno = 0,
     .out_st = {.st_mode = S_IRWXU,.st_uid = 1,.st_gid = 0,},
 },
 .mock_stat_leg_idx = {
     .want_path = "/path/to/file.db",
     .out_errno = 0,
     .out_st = {.st_mode = S_IRWXU,.st_uid = 1,.st_gid = 0,},
 },
 .mock_stat_parent = {
     .want_path = "/path/to",
     .out_errno = 0,
     .out_st = {.st_mode = S_IRWXU,.st_uid = 1,.st_gid = 0,},
 },
 .mock_stat_new_idx = {
     .want_path = "/path/to/file.cdb",
     .out_errno = ENOENT,
 },
 .mock_open = {
     .want_path = "/path/to/file",
     .want_uid = 0,
     .want_gid = 0,
     .out_errno = 0,
     .out_data = "foo bar\nfoo :bar",
 },
 .params = {
     .allow_root_pfxs = "/somewhere",
     .allow_user_pfxs = "/other/path",
     .migr_level = "enable-reindex",
 },
 .process = {
     .in_new_type = "hash",
     .in_source_path = "/path/to/file",
     .want_status = NBDB_STAT_ERROR,
     .want_why = "unexpected pathname",
 },
    },

    {0},
};

int     main(int argc, char **argv)
{
    const TEST_CASE *tp;
    int     pass = 0;
    int     fail = 0;

    msg_vstream_init(sane_basename((VSTRING *) 0, argv[0]), VSTREAM_ERR);

    for (tp = test_cases; tp->label != 0; tp++) {
 int     test_failed;

 msg_info("RUN  %s", tp->label);
 test_failed = tp->action(tp);
 if (test_failed) {
     msg_info("FAIL %s", tp->label);
     fail++;
 } else {
     msg_info("PASS %s", tp->label);
     pass++;
 }
    }
    msg_info("PASS=%d FAIL=%d", pass, fail);
    exit(fail != 0);
}

Messung V0.5 in Prozent
C=86 H=98 G=91

¤ Dauer der Verarbeitung: 0.18 Sekunden  (vorverarbeitet am  2026-08-08) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=141584
#Domains=738142