LCOV - code coverage report
Current view: top level - tests - tld_internal_test.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 79.4 % 63 50
Test Date: 2025-07-17 21:03:15 Functions: 100.0 % 5 5
Legend: Lines: hit not hit

            Line data    Source code
       1              : /* TLD library -- Test the TLD library by including the tld.c file.
       2              :  * Copyright (c) 2011-2023  Made to Order Software Corp.  All Rights Reserved
       3              :  *
       4              :  * Permission is hereby granted, free of charge, to any person obtaining a
       5              :  * copy of this software and associated documentation files (the
       6              :  * "Software"), to deal in the Software without restriction, including
       7              :  * without limitation the rights to use, copy, modify, merge, publish,
       8              :  * distribute, sublicense, and/or sell copies of the Software, and to
       9              :  * permit persons to whom the Software is furnished to do so, subject to
      10              :  * the following conditions:
      11              :  *
      12              :  * The above copyright notice and this permission notice shall be included
      13              :  * in all copies or substantial portions of the Software.
      14              :  *
      15              :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      16              :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
      17              :  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
      18              :  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
      19              :  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
      20              :  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
      21              :  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
      22              :  */
      23              : 
      24              : /** \file
      25              :  * \brief Test the tld.c, tld_data.c, and tld_domain_to_lowercase.c functions.
      26              :  *
      27              :  * This file implements various tests that can directly access the internal
      28              :  * functions of the tld.c, tld_data.c, and tld_domain_to_lowercase.c
      29              :  * files.
      30              :  *
      31              :  * For that purpose we directly include those files in this test. This
      32              :  * is why the test is not actually linked against the library, it
      33              :  * includes it within itself.
      34              :  */
      35              : 
      36              : // libtld sources
      37              : //
      38              : #include    <libtld/tld.cpp>
      39              : #include    <libtld/tld_file.cpp>
      40              : 
      41              : extern "C" {
      42              : #include    <libtld/tld_data.c>
      43              : #include    <libtld/tld_domain_to_lowercase.c>
      44              : #include    <libtld/tld_strings.c>
      45              : }
      46              : 
      47              : 
      48              : // C
      49              : //
      50              : #include    <stdlib.h>
      51              : #include    <string.h>
      52              : 
      53              : 
      54              : 
      55              : extern "C" {
      56              : 
      57              : 
      58              : int err_count = 0;
      59              : int verbose = 0;
      60              : 
      61            1 : void test_compare()
      62              : {
      63              :     struct data
      64              :     {
      65              :         const char *a;
      66              :         const char *b;
      67              :         int n;
      68              :         int r;
      69              :     };
      70            1 :     struct data d[] = {
      71              :         { "uj", "uk", 2, -1 },
      72              :         { "uk", "uk", 2,  0 },
      73              :         { "ul", "uk", 2,  1 },
      74              : 
      75              :         { "uj", "ukmore",  2, -1 },
      76              :         { "uk", "ukstuff", 2,  0 },
      77              :         { "ul", "ukhere",  2,  1 },
      78              : 
      79              :         { "uk1", "ukmore",  2, 1 },
      80              :         { "uk2", "ukstuff", 2, 1 },
      81              :         { "uk3", "ukhere",  2, 1 },
      82              : 
      83              :         { "uk1", "uk.", 3, 1 },
      84              :         { "uk2", "uk.", 3, 1 },
      85              :         { "uk3", "uk.", 3, 1 },
      86              : 
      87              :         { "uk1", ".uk", 3, 1 },
      88              :         { "uk2", ".uk", 3, 1 },
      89              :         { "uk3", ".uk", 3, 1 },
      90              : 
      91              :         { "uk", "uk1",   3, -1 },
      92              :         { "uk", "uk22",  4, -1 },
      93              :         { "uk", "uk333", 5, -1 },
      94              : 
      95              :         { "uk1",   "uk", 2, 1 },
      96              :         { "uk22",  "uk", 2, 1 },
      97              :         { "uk333", "uk", 2, 1 },
      98              :     };
      99              :     int i, r, max;
     100              :     char *s, *vd, *u;
     101              : 
     102            1 :     max = sizeof(d) / sizeof(d[0]);
     103           22 :     for(i = 0; i < max; ++i)
     104              :     {
     105           21 :         r = cmp(d[i].a, strlen(d[i].a), d[i].b, d[i].n);
     106           21 :         if(r != d[i].r) {
     107            0 :             fprintf(stderr, "error: cmp() failed with \"%s\" / \"%s\", expected %d and got %d [1]\n",
     108              :                     d[i].a, d[i].b, d[i].r, r);
     109            0 :             ++err_count;
     110              :         }
     111              : 
     112              :         // create a version with uppercase and try again
     113           21 :         s = strdup(d[i].b);
     114          101 :         for(u = s; *u != '\0'; ++u)
     115              :         {
     116           80 :             if(*u >= 'a' && *u <= 'z')
     117              :             {
     118           68 :                 *u &= 0x5F;
     119              :             }
     120              :         }
     121           21 :         vd = tld_domain_to_lowercase(s);
     122           21 :         r = cmp(d[i].a, strlen(d[i].a), d[i].b, d[i].n);
     123           21 :         if(r != d[i].r) {
     124            0 :             fprintf(stderr, "error: cmp() failed with \"%s\" / \"%s\", expected %d and got %d (with domain to lowercase) [2]\n",
     125              :                     d[i].a, d[i].b, d[i].r, r);
     126            0 :             ++err_count;
     127              :         }
     128           21 :         free(vd);
     129           21 :         free(s);
     130              :     }
     131            1 : }
     132              : 
     133            1 : void test_search()
     134              : {
     135              :     struct search_info
     136              :     {
     137              :         int                f_start;
     138              :         int                f_end;
     139              :         const char *    f_tld;
     140              :         int                f_length;
     141              :         int                f_result;
     142              :     };
     143            1 :     struct search_info d[] = {
     144              :         /*
     145              :          * This table is very annoying since each time the data changes
     146              :          * it gets out of sync. On the other hand that's the best way
     147              :          * to make sure our tests work like in the real world.
     148              :          */
     149              : 
     150              :         /* get the .uk offset */
     151              :         { 10339, 11965, "uk", 2, 11847 },
     152              : 
     153              :         /* get each offset of the .uk 2nd level domain */
     154              :         { 10013, 10043, "ac", 2,                         10013 },
     155              :         { 10013, 10043, "barsy", 5,                      10014 },
     156              :         { 10013, 10043, "co", 2,                         10015 },
     157              :         { 10013, 10043, "conn", 4,                       10016 },
     158              :         { 10013, 10043, "copro", 5,                      10017 },
     159              :         { 10013, 10043, "gov", 3,                        10018 },
     160              :         { 10013, 10043, "govt", 4,                       10019 },
     161              :         { 10013, 10043, "hosp", 4,                       10020 },
     162              :         { 10013, 10043, "icnet", 5,                      10021 },
     163              :         { 10013, 10043, "independent-commission", 22,    10022 },
     164              :         { 10013, 10043, "independent-inquest", 19,       10023 },
     165              :         { 10013, 10043, "independent-inquiry", 19,       10024 },
     166              :         { 10013, 10043, "independent-panel", 17,         10025 },
     167              :         { 10013, 10043, "independent-review", 18,        10026 },
     168              :         { 10013, 10043, "lea", 3,                        10027 },
     169              :         { 10013, 10043, "ltd", 3,                        10028 },
     170              :         { 10013, 10043, "me", 2,                         10029 },
     171              :         { 10013, 10043, "mil", 3,                        10030 },
     172              :         { 10013, 10043, "net", 3,                        10031 },
     173              :         { 10013, 10043, "nhs", 3,                        10032 },
     174              :         { 10013, 10043, "nimsite", 7,                    10033 },
     175              :         { 10013, 10043, "oraclegovcloudapps", 18,        10034 },
     176              :         { 10013, 10043, "org", 3,                        10035 },
     177              :         { 10013, 10043, "orgn", 4,                       10036 },
     178              :         { 10013, 10043, "plc", 3,                        10037 },
     179              :         { 10013, 10043, "police", 6,                     10038 },
     180              :         { 10013, 10043, "public-inquiry", 14,            10039 },
     181              :         { 10013, 10043, "pymnt", 5,                      10040 },
     182              :         { 10013, 10043, "royal-commission", 16,          10041 },
     183              :         { 10013, 10043, "sch", 3,                        10042 },
     184              : 
     185              :         /* test with a few invalid TLDs for .uk */
     186              :         { 10022, 10052, "com", 3, -1 },
     187              :         { 10022, 10052, "aca", 3, -1 },
     188              :         { 10022, 10052, "aac", 3, -1 },
     189              :         { 10022, 10052, "bl", 2, -1 },
     190              :         { 10022, 10052, "british-library", 15, -1 },
     191              :         { 10022, 10052, "ca", 2, -1 },
     192              :         { 10022, 10052, "cn", 2, -1 },
     193              :         { 10022, 10052, "cp", 2, -1 },
     194              :         { 10022, 10052, "cz", 2, -1 },
     195              :         { 10022, 10052, "jet", 3, -1 },
     196              :         { 10022, 10052, "mod", 3, -1 },
     197              :         { 10022, 10052, "national-library-scotland", 25, -1 },
     198              :         { 10022, 10052, "nel", 3, -1 },
     199              :         { 10022, 10052, "nic", 3, -1 },
     200              :         { 10022, 10052, "nls", 3, -1 },
     201              :         { 10022, 10052, "parliament", 10, -1 },
     202              :         { 10022, 10052, "school", 2, -1 },
     203              : 
     204              :         /* get the .vu offset */
     205              :         { 10339, 11965, "vu", 2, 11894 },
     206              : 
     207              :         /* get the 2nd level .vu offsets */
     208              :         { 10249, 10257, "blog", 4, 10249 },
     209              :         { 10249, 10257, "cn", 2,   10250 },
     210              :         { 10249, 10257, "com", 3,  10251 },
     211              :         { 10249, 10257, "dev", 3,  10252 },
     212              :         { 10249, 10257, "edu", 3,  10253 },
     213              :         { 10249, 10257, "me", 2,   10254 },
     214              :         { 10249, 10257, "net", 3,  10255 },
     215              :         { 10249, 10257, "org", 3,  10256 },
     216              : 
     217              :         /* test with a few .vu 2nd level domains that do not exist */
     218              :         { 10249, 10257, "gov", 3, -1 },
     219              :         { 10249, 10257, "nom", 3, -1 },
     220              :         { 10249, 10257, "sch", 3, -1 },
     221              :         { 10249, 10257, "zero", 4, -1 },
     222              : 
     223              :         /* verify ordering of mari, mari-el, and marine (from .ru) */
     224              :         { 9282, 9432, "mari",    4, 9349 },
     225              :         { 9282, 9432, "mari-el", 7, 9350 },
     226              :         { 9282, 9432, "marine",  6, 9351 },
     227              :     };
     228              : 
     229              :     size_t i;
     230              : 
     231            1 :     size_t const max = sizeof(d) / sizeof(d[0]);
     232           65 :     for(i = 0; i < max; ++i)
     233              :     {
     234           64 :         int const r = search(d[i].f_start, d[i].f_end, d[i].f_tld, d[i].f_length);
     235           64 :         if(r != d[i].f_result)
     236              :         {
     237            0 :             fprintf(stderr, "error: test_search() failed with \"%s\", expected %d and got %d [3]\n",
     238              :                     d[i].f_tld, d[i].f_result, r);
     239            0 :             ++err_count;
     240              :         }
     241              :     }
     242            1 : }
     243              : 
     244              : 
     245         1107 : void test_search_array(int start, int end)
     246              : {
     247         1107 :     const struct tld_description *  tld(nullptr);
     248         1107 :     int                             i(0), r(0);
     249         1107 :     uint32_t                        l(0);
     250         1107 :     const char *                    name(nullptr);
     251              : 
     252              :     /* now test all from the arrays */
     253        13072 :     for(i = start; i < end; ++i)
     254              :     {
     255        11965 :         tld = tld_file_description(g_tld_file, i);
     256        11965 :         name = tld_file_string(g_tld_file, tld->f_tld, &l);
     257        11965 :         if(verbose)
     258              :         {
     259            0 :             printf("{%d..%d} i = %d, [%.*s]\n", start, end, i, l, name);
     260              :         }
     261        11965 :         r = search(start, end, name, l);
     262        11965 :         if(r != i)
     263              :         {
     264            0 :             fprintf(stderr, "error: test_search_array() failed with \"%.*s\", expected %d and got %d [4]\n",
     265              :                     l, name, i, r);
     266            0 :             ++err_count;
     267              :         }
     268        11965 :         if(tld->f_start_offset != USHRT_MAX)
     269              :         {
     270         1106 :             test_search_array(tld->f_start_offset, tld->f_end_offset);
     271              :         }
     272              :     }
     273         1107 : }
     274              : 
     275            1 : void test_search_all()
     276              : {
     277            1 :     test_search_array(
     278            1 :               g_tld_file->f_header->f_tld_start_offset
     279            1 :             , g_tld_file->f_header->f_tld_end_offset);
     280            1 : }
     281              : 
     282              : 
     283            1 : int main(int argc, char *argv[])
     284              : {
     285            1 :     fprintf(stderr, "testing internal tld version %s\n", tld_version());
     286              : 
     287            1 :     if(argc > 1)
     288              :     {
     289            0 :         if(strcmp(argv[1], "-v") == 0)
     290              :         {
     291            0 :             verbose = 1;
     292              :         }
     293              :     }
     294              : 
     295              :     /* call all the tests, one by one
     296              :      * failures are "recorded" in the err_count global variable
     297              :      * and the process stops with an error message and exit(1)
     298              :      * if err_count is not zero.
     299              :      */
     300            1 :     test_compare();
     301            1 :     test_search();
     302            1 :     test_search_all();
     303              : 
     304            1 :     if(err_count)
     305              :     {
     306            0 :         fprintf(stderr, "%d error%s occured.\n",
     307            0 :                     err_count, err_count != 1 ? "s" : "");
     308              :     }
     309            1 :     exit(err_count ? 1 : 0);
     310              : }
     311              : 
     312              : } // extern "C"
     313              : 
     314              : // vim: ts=4 sw=4 et
        

Generated by: LCOV version 2.0-1

Snap C++ | List of projects | List of versions