LCOV - code coverage report
Current view: top level - lib/ldb/tests - test_ldb_comparison_fold.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 38 40 95.0 %
Date: 2024-05-31 13:13:24 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Unix SMB/CIFS implementation.
       3             :  *
       4             :  * Copyright (C) 2018      Andreas Schneider <asn@samba.org>
       5             :  * Copyright (C) 2024      Douglas Bagnall   <dbagnall@samba.org>
       6             :  *
       7             :  * This program is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU General Public License as published by
       9             :  * the Free Software Foundation; either version 3 of the License, or
      10             :  * (at your option) any later version.
      11             :  *
      12             :  * This program is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include <stdarg.h>
      22             : #include <stddef.h>
      23             : #include <setjmp.h>
      24             : #include <cmocka.h>
      25             : #include <stdbool.h>
      26             : #include "replace.h"
      27             : #include "ldb.h"
      28             : #include "ldb_private.h"
      29             : #include "ldb_handlers.h"
      30             : #include "util/tsort.h"
      31             : #include "ldb-samba/ldb_wrap.h"
      32             : 
      33             : 
      34             : #define debug_message(...)  do {                        \
      35             :                 if (isatty(1)) {                        \
      36             :                         print_message(__VA_ARGS__);     \
      37             :                                 }                       \
      38             :         } while(0)
      39             : 
      40             : /*
      41             :  * We use sets of string values paired with integer rankings and make every
      42             :  * pair-wise comparison (both ways: cmp(a,b) and cmp(b,a)). The strings should
      43             :  * be consistently ordered in the same way as the integers.
      44             :  *
      45             :  * There are separate sets for the default ldb ASCII comparison, and for
      46             :  * Samba's utf-8 aware comparisons, and a common set that both of them should
      47             :  * pass.
      48             :  */
      49             : 
      50             : struct ranked_value {
      51             :         struct ldb_val val;
      52             :         int rank;
      53             : };
      54             : 
      55             : #define STR_VAL(s, r) { { discard_const(s), sizeof(s) - 1 }, r}
      56             : 
      57             : static const struct ranked_value values_common[] = {
      58             :         STR_VAL("", 0),
      59             :         STR_VAL("    ", 0),
      60             :         STR_VAL("a", 10),
      61             :         STR_VAL(" A\0 ignored-post-zero", 10),
      62             :         STR_VAL("a   b", 15),
      63             :         STR_VAL("a     B ", 15),
      64             :         STR_VAL("    A b", 15),
      65             : 
      66             :         STR_VAL("a\xc2\xfe", 30),
      67             :         STR_VAL("a\xc2\xfe  a", 32),
      68             :         STR_VAL("a\xc2\xfe A", 32),
      69             :         STR_VAL("a\xc2\xfe Ā", 35),
      70             :         STR_VAL("A\xc2\xfe       Ā", 35),
      71             :         STR_VAL("a\xc2\xfe ā", 37),
      72             :         STR_VAL("a\xff\xfe ā", 40),
      73             : 
      74             :         STR_VAL("b", 50),
      75             : 
      76             :         STR_VAL("\xff\xfe", 1000),
      77             : };
      78             : 
      79             : static const struct ranked_value values_default_ascii[] = {
      80             :         STR_VAL(" a", 1),
      81             : 
      82             :         STR_VAL("b", 50),
      83             :         STR_VAL("Ā", 256),
      84             :         STR_VAL("  Ā", 256),
      85             :         STR_VAL("ā", 257),
      86             :         STR_VAL("ā  ", 257),
      87             : 
      88             :         STR_VAL("Ʊ", 433),
      89             :         STR_VAL("\xc8\xfe", 500),
      90             :         STR_VAL("ʊ", 650),
      91             : 
      92             :         STR_VAL("\xff\xfe", 1000),
      93             : };
      94             : 
      95             : static const struct ranked_value values_utf8[] = {
      96             :         STR_VAL(" a", 1),
      97             : 
      98             :         STR_VAL("b", 50),
      99             :         STR_VAL("Ā", 256),
     100             :         STR_VAL("  Ā", 256),
     101             :         STR_VAL("ā", 256),
     102             :         STR_VAL("ā  ", 256),
     103             : 
     104             :         STR_VAL("Ʊ", 433),
     105             :         STR_VAL("ʊ", 433),
     106             :         STR_VAL("\xc8\xfe", 900),
     107             : 
     108             :         STR_VAL("\xff\xfe", 1000),
     109             : };
     110             : 
     111             : 
     112             : 
     113             : #undef STR_VAL
     114             : 
     115             : 
     116           4 : static void _test_ldb_comparison_fold_set(struct ldb_context *ldb,
     117             :                                           const struct ranked_value *values,
     118             :                                           size_t n)
     119             : {
     120           4 :         size_t i, j;
     121           4 :         size_t n_errors = 0;
     122             : 
     123          56 :         for (i = 0; i < n; i++) {
     124          52 :                 struct ranked_value a = values[i];
     125         764 :                 for (j = 0; j < n; j++) {
     126         712 :                         struct ranked_value b = values[j];
     127         712 :                         int ret = ldb_comparison_fold(ldb, NULL, &a.val, &b.val);
     128         712 :                         if ((ret < 0 && a.rank < b.rank) ||
     129         405 :                             (ret == 0 && a.rank == b.rank) ||
     130         307 :                             (ret > 0 && a.rank > b.rank)) {
     131         712 :                                 continue;
     132             :                         }
     133           0 :                         debug_message("A {'%s', %zu} vs B {'%s', %zu} returned %d,"
     134             :                                       "should be %d (%d - %d)\n",
     135             :                                       a.val.data, a.val.length, b.val.data, b.val.length, ret,
     136             :                                       NUMERIC_CMP(a.rank, b.rank), a.rank, b.rank);
     137             : 
     138           0 :                         n_errors++;
     139             :                 }
     140             :         }
     141           4 :         debug_message("%zu errors out of %zu\n", n_errors, n * n);
     142             : 
     143           4 :         assert_int_equal(n_errors, 0);
     144           4 : }
     145             : 
     146             : 
     147             : /*
     148             :  * These tests are for the specific behaviour of the default ASCII-only
     149             :  * casefold.
     150             :  */
     151           1 : static void test_ldb_comparison_fold_default_ascii(void **state)
     152             : {
     153           1 :         struct ldb_context *ldb = ldb_init(NULL, NULL);
     154           1 :         _test_ldb_comparison_fold_set(ldb,
     155             :                                       values_default_ascii,
     156             :                                       ARRAY_SIZE(values_default_ascii));
     157           1 : }
     158             : 
     159             : 
     160             : /*
     161             :  * These tests are for behaviour with the default comparison, that should work
     162             :  * the same with the Samba utf-8 comparison.
     163             :  */
     164           1 : static void test_ldb_comparison_fold_default_common(void **state)
     165             : {
     166           1 :         struct ldb_context *ldb = ldb_init(NULL, NULL);
     167           1 :         _test_ldb_comparison_fold_set(ldb,
     168             :                                       values_common,
     169             :                                       ARRAY_SIZE(values_common));
     170           1 : }
     171             : 
     172             : 
     173             : /*
     174             :  * These tests are for behaviour with the Samba utf-8 comparison, that should
     175             :  * work the same with the default ASCII comparison.
     176             :  */
     177           1 : static void test_ldb_comparison_fold_utf8_common(void **state)
     178             : {
     179           1 :         struct ldb_context *ldb = ldb_init(NULL, NULL);
     180           1 :         ldb_set_utf8_functions(ldb, NULL, wrap_casefold, ldb_comparison_fold_utf8);
     181           1 :         _test_ldb_comparison_fold_set(ldb,
     182             :                                       values_common,
     183             :                                       ARRAY_SIZE(values_common));
     184           1 : }
     185             : 
     186             : /*
     187             :  * These tests are for the specific behaviour of the default ASCII-only
     188             :  * casefold.
     189             :  */
     190           1 : static void test_ldb_comparison_fold_utf8(void **state)
     191             : {
     192           1 :         struct ldb_context *ldb = ldb_init(NULL, NULL);
     193           1 :         ldb_set_utf8_functions(ldb, NULL, wrap_casefold, ldb_comparison_fold_utf8);
     194           1 :         _test_ldb_comparison_fold_set(ldb,
     195             :                                       values_utf8,
     196             :                                       ARRAY_SIZE(values_utf8));
     197           1 : }
     198             : 
     199             : 
     200             : 
     201             : 
     202           1 : int main(void) {
     203           1 :         const struct CMUnitTest tests[] = {
     204             :                 cmocka_unit_test(test_ldb_comparison_fold_default_common),
     205             :                 cmocka_unit_test(test_ldb_comparison_fold_default_ascii),
     206             :                 cmocka_unit_test(test_ldb_comparison_fold_utf8_common),
     207             :                 cmocka_unit_test(test_ldb_comparison_fold_utf8),
     208             :         };
     209           1 :         if (!isatty(1)) {
     210           1 :                 cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
     211             :         }
     212           1 :         return cmocka_run_group_tests(tests, NULL, NULL);
     213             : }

Generated by: LCOV version 1.14