LCOV - code coverage report
Current view: top level - tests - tld_internal_test.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 51 64 79.7 %
Date: 2022-02-19 13:28:04 Functions: 7 7 100.0 %
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-2022  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 library 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 lib
      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             :         { 8842, 10464, "uk", 2, 10346 },
     152             : 
     153             :         /* get each offset of the .uk 2nd level domain */
     154             :         { 8595, 8625, "ac", 2,                         8595 },
     155             :         { 8595, 8625, "barsy", 5,                      8596 },
     156             :         { 8595, 8625, "bl", 2,                         8597 },
     157             :         { 8595, 8625, "british-library", 15,           8598 },
     158             :         { 8595, 8625, "co", 2,                         8599 },
     159             :         { 8595, 8625, "conn", 4,                       8600 },
     160             :         { 8595, 8625, "copro", 5,                      8601 },
     161             :         { 8595, 8625, "gov", 3,                        8602 },
     162             :         { 8595, 8625, "govt", 4,                       8603 },
     163             :         { 8595, 8625, "hosp", 4,                       8604 },
     164             :         { 8595, 8625, "icnet", 5,                      8605 },
     165             :         { 8595, 8625, "jet", 3,                        8606 },
     166             :         { 8595, 8625, "lea", 3,                        8607 },
     167             :         { 8595, 8625, "ltd", 3,                        8608 },
     168             :         { 8595, 8625, "me", 2,                         8609 },
     169             :         { 8595, 8625, "mil", 3,                        8610 },
     170             :         { 8595, 8625, "mod", 3,                        8611 },
     171             :         { 8595, 8625, "national-library-scotland", 25, 8612 },
     172             :         { 8595, 8625, "nel", 3,                        8613 },
     173             :         { 8595, 8625, "net", 3,                        8614 },
     174             :         { 8595, 8625, "nhs", 3,                        8615 },
     175             :         { 8595, 8625, "nic", 3,                        8616 },
     176             :         { 8595, 8625, "nls", 3,                        8617 },
     177             :         { 8595, 8625, "org", 3,                        8618 },
     178             :         { 8595, 8625, "orgn", 4,                       8619 },
     179             :         { 8595, 8625, "parliament", 10,                8620 },
     180             :         { 8595, 8625, "plc", 3,                        8621 },
     181             :         { 8595, 8625, "police", 6,                     8622 },
     182             :         { 8595, 8625, "pymnt", 5,                      8623 },
     183             :         { 8595, 8625, "sch", 3,                        8624 },
     184             : 
     185             :         /* test with a few invalid TLDs for .uk */
     186             :         { 8595, 8625, "com", 3, -1 },
     187             :         { 8595, 8625, "aca", 3, -1 },
     188             :         { 8595, 8625, "aac", 3, -1 },
     189             :         { 8595, 8625, "ca", 2, -1 },
     190             :         { 8595, 8625, "cn", 2, -1 },
     191             :         { 8595, 8625, "cp", 2, -1 },
     192             :         { 8595, 8625, "cz", 2, -1 },
     193             :         { 8595, 8625, "school", 2, -1 },
     194             : 
     195             :         /* get the .vu offset */
     196             :         { 8842, 10464, "vu", 2, 10393 },
     197             : 
     198             :         /* get the 2nd level .vu offsets */
     199             :         { 8755, 8764, "blog", 4, 8755 },
     200             :         { 8755, 8764, "cn", 2,   8756 },
     201             :         { 8755, 8764, "com", 3,  8757 },
     202             :         { 8755, 8764, "dev", 3,  8758 },
     203             :         { 8755, 8764, "edu", 3,  8759 },
     204             :         { 8755, 8764, "gov", 3,  8760 },
     205             :         { 8755, 8764, "me", 2,   8761 },
     206             :         { 8755, 8764, "net", 3,  8762 },
     207             :         { 8755, 8764, "org", 3,  8763 },
     208             : 
     209             :         /* test with a few .vu 2nd level domains that do not exist */
     210             :         { 8755, 8764, "nom", 3, -1 },
     211             :         { 8755, 8764, "sch", 3, -1 },
     212             :         { 8755, 8764, "zero", 4, -1 },
     213             : 
     214             :         /* verify ordering of mari, mari-el, and marine (from .ru) */
     215             :         { 7928, 8077, "mari",    4, 7994 },
     216             :         { 7928, 8077, "mari-el", 7, 7995 },
     217             :         { 7928, 8077, "marine",  6, 7996 },
     218             :     };
     219             : 
     220             :     size_t i;
     221             : 
     222           1 :     size_t const max = sizeof(d) / sizeof(d[0]);
     223          56 :     for(i = 0; i < max; ++i)
     224             :     {
     225          55 :         int const r = search(d[i].f_start, d[i].f_end, d[i].f_tld, d[i].f_length);
     226          55 :         if(r != d[i].f_result)
     227             :         {
     228           0 :             fprintf(stderr, "error: test_search() failed with \"%s\", expected %d and got %d [3]\n",
     229             :                     d[i].f_tld, d[i].f_result, r);
     230           0 :             ++err_count;
     231             :         }
     232             :     }
     233           1 : }
     234             : 
     235             : 
     236         796 : void test_search_array(int start, int end)
     237             : {
     238         796 :     const struct tld_description *  tld(nullptr);
     239         796 :     int                             i(0), r(0);
     240         796 :     uint32_t                        l(0);
     241         796 :     const char *                    name(nullptr);
     242             : 
     243             :     /* now test all from the arrays */
     244       11260 :     for(i = start; i < end; ++i)
     245             :     {
     246       10464 :         tld = tld_file_description(g_tld_file, i);
     247       10464 :         name = tld_file_string(g_tld_file, tld->f_tld, &l);
     248       10464 :         if(verbose)
     249             :         {
     250           0 :             printf("{%d..%d} i = %d, [%.*s]\n", start, end, i, l, name);
     251             :         }
     252       10464 :         r = search(start, end, name, l);
     253       10464 :         if(r != i)
     254             :         {
     255           0 :             fprintf(stderr, "error: test_search_array() failed with \"%.*s\", expected %d and got %d [4]\n",
     256             :                     l, name, i, r);
     257           0 :             ++err_count;
     258             :         }
     259       10464 :         if(tld->f_start_offset != USHRT_MAX)
     260             :         {
     261         795 :             test_search_array(tld->f_start_offset, tld->f_end_offset);
     262             :         }
     263             :     }
     264         796 : }
     265             : 
     266           1 : void test_search_all()
     267             : {
     268           2 :     test_search_array(
     269           1 :               g_tld_file->f_header->f_tld_start_offset
     270           1 :             , g_tld_file->f_header->f_tld_end_offset);
     271           1 : }
     272             : 
     273             : 
     274           1 : int main(int argc, char *argv[])
     275             : {
     276           1 :     fprintf(stderr, "testing internal tld version %s\n", tld_version());
     277             : 
     278           1 :     if(argc > 1)
     279             :     {
     280           0 :         if(strcmp(argv[1], "-v") == 0)
     281             :         {
     282           0 :             verbose = 1;
     283             :         }
     284             :     }
     285             : 
     286             :     /* call all the tests, one by one
     287             :      * failures are "recorded" in the err_count global variable
     288             :      * and the process stops with an error message and exit(1)
     289             :      * if err_count is not zero.
     290             :      */
     291           1 :     test_compare();
     292           1 :     test_search();
     293           1 :     test_search_all();
     294             : 
     295           1 :     if(err_count)
     296             :     {
     297           0 :         fprintf(stderr, "%d error%s occured.\n",
     298           0 :                     err_count, err_count != 1 ? "s" : "");
     299             :     }
     300           1 :     exit(err_count ? 1 : 0);
     301             : }
     302             : 
     303           3 : } // extern "C"
     304             : 
     305             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.13