LCOV - code coverage report
Current view: top level - test - test_geoip.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 275 276 99.6 %
Date: 2021-11-24 03:28:48 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /* Copyright (c) 2001-2004, Roger Dingledine.
       2             :  * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
       3             :  * Copyright (c) 2007-2021, The Tor Project, Inc. */
       4             : /* See LICENSE for licensing information */
       5             : 
       6             : #include "orconfig.h"
       7             : 
       8             : /* These macros pull in declarations for some functions and structures that
       9             :  * are typically file-private. */
      10             : #define GEOIP_PRIVATE
      11             : #include "core/or/or.h"
      12             : #include "app/config/config.h"
      13             : #include "lib/geoip/geoip.h"
      14             : #include "feature/stats/geoip_stats.h"
      15             : #include "test/test.h"
      16             : 
      17             :   /* Record odd numbered fake-IPs using ipv6, even numbered fake-IPs
      18             :    * using ipv4.  Since our fake geoip database is the same between
      19             :    * ipv4 and ipv6, we should get the same result no matter which
      20             :    * address family we pick for each IP. */
      21             : #define SET_TEST_ADDRESS(i) do {                \
      22             :     if ((i) & 1) {                              \
      23             :       SET_TEST_IPV6(i);                         \
      24             :       tor_addr_from_in6(&addr, &in6);           \
      25             :     } else {                                    \
      26             :       tor_addr_from_ipv4h(&addr, (uint32_t) i); \
      27             :     }                                           \
      28             :   } while (0)
      29             : 
      30             :   /* Make sure that country ID actually works. */
      31             : #define SET_TEST_IPV6(i) \
      32             :   do {                                                          \
      33             :     set_uint32(in6.s6_addr + 12, htonl((uint32_t) (i)));        \
      34             :   } while (0)
      35             : #define CHECK_COUNTRY(country, val) do {                                \
      36             :     /* test ipv4 country lookup */                                      \
      37             :     tt_str_op(country, OP_EQ,                                              \
      38             :                geoip_get_country_name(geoip_get_country_by_ipv4(val))); \
      39             :     /* test ipv6 country lookup */                                      \
      40             :     SET_TEST_IPV6(val);                                                 \
      41             :     tt_str_op(country, OP_EQ,                                              \
      42             :                geoip_get_country_name(geoip_get_country_by_ipv6(&in6))); \
      43             :   } while (0)
      44             : 
      45             : /** Run unit tests for GeoIP code. */
      46             : static void
      47           1 : test_geoip(void *arg)
      48             : {
      49           1 :   int i, j;
      50           1 :   time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
      51           1 :   char *s = NULL, *v = NULL;
      52           1 :   const char *bridge_stats_1 =
      53             :       "bridge-stats-end 2010-08-12 13:27:30 (86400 s)\n"
      54             :       "bridge-ips zz=24,xy=8\n"
      55             :       "bridge-ip-versions v4=16,v6=16\n"
      56             :       "bridge-ip-transports <OR>=24\n",
      57           1 :   *dirreq_stats_1 =
      58             :       "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n"
      59             :       "dirreq-v3-ips ab=8\n"
      60             :       "dirreq-v3-reqs ab=8\n"
      61             :       "dirreq-v3-resp ok=0,not-enough-sigs=0,unavailable=0,not-found=0,"
      62             :           "not-modified=0,busy=0\n"
      63             :       "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
      64             :       "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n",
      65           1 :   *dirreq_stats_2 =
      66             :       "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n"
      67             :       "dirreq-v3-ips \n"
      68             :       "dirreq-v3-reqs \n"
      69             :       "dirreq-v3-resp ok=0,not-enough-sigs=0,unavailable=0,not-found=0,"
      70             :           "not-modified=0,busy=0\n"
      71             :       "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
      72             :       "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n",
      73           1 :   *dirreq_stats_3 =
      74             :       "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n"
      75             :       "dirreq-v3-ips \n"
      76             :       "dirreq-v3-reqs \n"
      77             :       "dirreq-v3-resp ok=8,not-enough-sigs=0,unavailable=0,not-found=0,"
      78             :           "not-modified=0,busy=0\n"
      79             :       "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
      80             :       "dirreq-v3-tunneled-dl complete=0,timeout=0,running=0\n",
      81           1 :   *dirreq_stats_4 =
      82             :       "dirreq-stats-end 2010-08-12 13:27:30 (86400 s)\n"
      83             :       "dirreq-v3-ips \n"
      84             :       "dirreq-v3-reqs \n"
      85             :       "dirreq-v3-resp ok=8,not-enough-sigs=0,unavailable=0,not-found=0,"
      86             :           "not-modified=0,busy=0\n"
      87             :       "dirreq-v3-direct-dl complete=0,timeout=0,running=0\n"
      88             :       "dirreq-v3-tunneled-dl complete=0,timeout=0,running=4\n",
      89           1 :   *entry_stats_1 =
      90             :       "entry-stats-end 2010-08-12 13:27:30 (86400 s)\n"
      91             :       "entry-ips ab=8\n",
      92           1 :   *entry_stats_2 =
      93             :       "entry-stats-end 2010-08-12 13:27:30 (86400 s)\n"
      94             :       "entry-ips \n";
      95           1 :   tor_addr_t addr;
      96           1 :   struct in6_addr in6;
      97             : 
      98             :   /* Populate the DB a bit.  Add these in order, since we can't do the final
      99             :    * 'sort' step.  These aren't very good IP addresses, but they're perfectly
     100             :    * fine uint32_t values. */
     101           1 :   (void)arg;
     102           1 :   tt_int_op(0,OP_EQ, geoip_parse_entry("10,50,AB", AF_INET));
     103           1 :   tt_int_op(0,OP_EQ, geoip_parse_entry("52,90,XY", AF_INET));
     104           1 :   tt_int_op(0,OP_EQ, geoip_parse_entry("95,100,AB", AF_INET));
     105           1 :   tt_int_op(0,OP_EQ, geoip_parse_entry("\"105\",\"140\",\"ZZ\"", AF_INET));
     106           1 :   tt_int_op(0,OP_EQ, geoip_parse_entry("\"150\",\"190\",\"XY\"", AF_INET));
     107           1 :   tt_int_op(0,OP_EQ, geoip_parse_entry("\"200\",\"250\",\"AB\"", AF_INET));
     108             : 
     109             :   /* Populate the IPv6 DB equivalently with fake IPs in the same range */
     110           1 :   tt_int_op(0,OP_EQ, geoip_parse_entry("::a,::32,AB", AF_INET6));
     111           1 :   tt_int_op(0,OP_EQ, geoip_parse_entry("::34,::5a,XY", AF_INET6));
     112           1 :   tt_int_op(0,OP_EQ, geoip_parse_entry("::5f,::64,AB", AF_INET6));
     113           1 :   tt_int_op(0,OP_EQ, geoip_parse_entry("::69,::8c,ZZ", AF_INET6));
     114           1 :   tt_int_op(0,OP_EQ, geoip_parse_entry("::96,::be,XY", AF_INET6));
     115           1 :   tt_int_op(0,OP_EQ, geoip_parse_entry("::c8,::fa,AB", AF_INET6));
     116             : 
     117             :   /* We should have 4 countries: ??, ab, xy, zz. */
     118           1 :   tt_int_op(4,OP_EQ, geoip_get_n_countries());
     119           1 :   memset(&in6, 0, sizeof(in6));
     120             : 
     121           1 :   CHECK_COUNTRY("??", 3);
     122           1 :   CHECK_COUNTRY("ab", 32);
     123           1 :   CHECK_COUNTRY("??", 5);
     124           1 :   CHECK_COUNTRY("??", 51);
     125           1 :   CHECK_COUNTRY("xy", 150);
     126           1 :   CHECK_COUNTRY("xy", 190);
     127           1 :   CHECK_COUNTRY("??", 2000);
     128             : 
     129           1 :   tt_int_op(0,OP_EQ, geoip_get_country_by_ipv4(3));
     130           1 :   SET_TEST_IPV6(3);
     131           1 :   tt_int_op(0,OP_EQ, geoip_get_country_by_ipv6(&in6));
     132             : 
     133           1 :   get_options_mutable()->BridgeRelay = 1;
     134           1 :   get_options_mutable()->BridgeRecordUsageByCountry = 1;
     135             :   /* Put 9 observations in AB... */
     136           9 :   for (i=32; i < 40; ++i) {
     137           8 :     SET_TEST_ADDRESS(i);
     138           8 :     geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-7200);
     139             :   }
     140           1 :   SET_TEST_ADDRESS(225);
     141           1 :   geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-7200);
     142             :   /* and 3 observations in XY, several times. */
     143          12 :   for (j=0; j < 10; ++j)
     144          40 :     for (i=52; i < 55; ++i) {
     145          30 :       SET_TEST_ADDRESS(i);
     146          30 :       geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-3600);
     147             :     }
     148             :   /* and 17 observations in ZZ... */
     149          18 :   for (i=110; i < 127; ++i) {
     150          17 :     SET_TEST_ADDRESS(i);
     151          17 :     geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
     152             :   }
     153           1 :   geoip_get_client_history(GEOIP_CLIENT_CONNECT, &s, &v);
     154           1 :   tt_assert(s);
     155           1 :   tt_assert(v);
     156           1 :   tt_str_op("zz=24,ab=16,xy=8",OP_EQ, s);
     157           1 :   tt_str_op("v4=16,v6=16",OP_EQ, v);
     158           1 :   tor_free(s);
     159           1 :   tor_free(v);
     160             : 
     161             :   /* Now clear out all the AB observations. */
     162           1 :   geoip_remove_old_clients(now-6000);
     163           1 :   geoip_get_client_history(GEOIP_CLIENT_CONNECT, &s, &v);
     164           1 :   tt_assert(s);
     165           1 :   tt_assert(v);
     166           1 :   tt_str_op("zz=24,xy=8",OP_EQ, s);
     167           1 :   tt_str_op("v4=16,v6=16",OP_EQ, v);
     168           1 :   tor_free(s);
     169           1 :   tor_free(v);
     170             : 
     171             :   /* Start testing bridge statistics by making sure that we don't output
     172             :    * bridge stats without initializing them. */
     173           1 :   s = geoip_format_bridge_stats(now + 86400);
     174           1 :   tt_ptr_op(s, OP_EQ, NULL);
     175             : 
     176             :   /* Initialize stats and generate the bridge-stats history string out of
     177             :    * the connecting clients added above. */
     178           1 :   geoip_bridge_stats_init(now);
     179           1 :   s = geoip_format_bridge_stats(now + 86400);
     180           1 :   tt_assert(s);
     181           1 :   tt_str_op(bridge_stats_1,OP_EQ, s);
     182           1 :   tor_free(s);
     183             : 
     184             :   /* Stop collecting bridge stats and make sure we don't write a history
     185             :    * string anymore. */
     186           1 :   geoip_bridge_stats_term();
     187           1 :   s = geoip_format_bridge_stats(now + 86400);
     188           1 :   tt_ptr_op(s, OP_EQ, NULL);
     189             : 
     190             :   /* Stop being a bridge and start being a directory mirror that gathers
     191             :    * directory request statistics. */
     192           1 :   geoip_bridge_stats_term();
     193           1 :   get_options_mutable()->BridgeRelay = 0;
     194           1 :   get_options_mutable()->BridgeRecordUsageByCountry = 0;
     195           1 :   get_options_mutable()->DirReqStatistics = 1;
     196             : 
     197             :   /* Start testing dirreq statistics by making sure that we don't collect
     198             :    * dirreq stats without initializing them. */
     199           1 :   SET_TEST_ADDRESS(100);
     200           1 :   geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now);
     201           1 :   s = geoip_format_dirreq_stats(now + 86400);
     202           1 :   tt_ptr_op(s, OP_EQ, NULL);
     203             : 
     204             :   /* Initialize stats, note one connecting client, and generate the
     205             :    * dirreq-stats history string. */
     206           1 :   geoip_dirreq_stats_init(now);
     207           1 :   SET_TEST_ADDRESS(100);
     208           1 :   geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now);
     209           1 :   s = geoip_format_dirreq_stats(now + 86400);
     210           1 :   tt_str_op(dirreq_stats_1,OP_EQ, s);
     211           1 :   tor_free(s);
     212             : 
     213             :   /* Stop collecting stats, add another connecting client, and ensure we
     214             :    * don't generate a history string. */
     215           1 :   geoip_dirreq_stats_term();
     216           1 :   SET_TEST_ADDRESS(101);
     217           1 :   geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now);
     218           1 :   s = geoip_format_dirreq_stats(now + 86400);
     219           1 :   tt_ptr_op(s, OP_EQ, NULL);
     220             : 
     221             :   /* Re-start stats, add a connecting client, reset stats, and make sure
     222             :    * that we get an all empty history string. */
     223           1 :   geoip_dirreq_stats_init(now);
     224           1 :   SET_TEST_ADDRESS(100);
     225           1 :   geoip_note_client_seen(GEOIP_CLIENT_NETWORKSTATUS, &addr, NULL, now);
     226           1 :   geoip_reset_dirreq_stats(now);
     227           1 :   s = geoip_format_dirreq_stats(now + 86400);
     228           1 :   tt_str_op(dirreq_stats_2,OP_EQ, s);
     229           1 :   tor_free(s);
     230             : 
     231             :   /* Note a successful network status response and make sure that it
     232             :    * appears in the history string. */
     233           1 :   geoip_note_ns_response(GEOIP_SUCCESS);
     234           1 :   s = geoip_format_dirreq_stats(now + 86400);
     235           1 :   tt_str_op(dirreq_stats_3,OP_EQ, s);
     236           1 :   tor_free(s);
     237             : 
     238             :   /* Start a tunneled directory request. */
     239           1 :   geoip_start_dirreq((uint64_t) 1, 1024, DIRREQ_TUNNELED);
     240           1 :   s = geoip_format_dirreq_stats(now + 86400);
     241           1 :   tt_str_op(dirreq_stats_4,OP_EQ, s);
     242           1 :   tor_free(s);
     243             : 
     244             :   /* Stop collecting directory request statistics and start gathering
     245             :    * entry stats. */
     246           1 :   geoip_dirreq_stats_term();
     247           1 :   get_options_mutable()->DirReqStatistics = 0;
     248           1 :   get_options_mutable()->EntryStatistics = 1;
     249             : 
     250             :   /* Start testing entry statistics by making sure that we don't collect
     251             :    * anything without initializing entry stats. */
     252           1 :   SET_TEST_ADDRESS(100);
     253           1 :   geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
     254           1 :   s = geoip_format_entry_stats(now + 86400);
     255           1 :   tt_ptr_op(s, OP_EQ, NULL);
     256             : 
     257             :   /* Initialize stats, note one connecting client, and generate the
     258             :    * entry-stats history string. */
     259           1 :   geoip_entry_stats_init(now);
     260           1 :   SET_TEST_ADDRESS(100);
     261           1 :   geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
     262           1 :   s = geoip_format_entry_stats(now + 86400);
     263           1 :   tt_str_op(entry_stats_1,OP_EQ, s);
     264           1 :   tor_free(s);
     265             : 
     266             :   /* Stop collecting stats, add another connecting client, and ensure we
     267             :    * don't generate a history string. */
     268           1 :   geoip_entry_stats_term();
     269           1 :   SET_TEST_ADDRESS(101);
     270           1 :   geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
     271           1 :   s = geoip_format_entry_stats(now + 86400);
     272           1 :   tt_ptr_op(s, OP_EQ, NULL);
     273             : 
     274             :   /* Re-start stats, add a connecting client, reset stats, and make sure
     275             :    * that we get an all empty history string. */
     276           1 :   geoip_entry_stats_init(now);
     277           1 :   SET_TEST_ADDRESS(100);
     278           1 :   geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now);
     279           1 :   geoip_reset_entry_stats(now);
     280           1 :   s = geoip_format_entry_stats(now + 86400);
     281           1 :   tt_str_op(entry_stats_2,OP_EQ, s);
     282           1 :   tor_free(s);
     283             : 
     284             :   /* Test the OOM handler. Add a client, run the OOM. */
     285           1 :   geoip_entry_stats_init(now);
     286           1 :   SET_TEST_ADDRESS(100);
     287           1 :   geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL,
     288             :                          now - (12 * 60 * 60));
     289             :   /* We've seen this 12 hours ago. Run the OOM, it should clean the entry
     290             :    * because it is above the minimum cutoff of 4 hours. */
     291           1 :   size_t bytes_removed = geoip_client_cache_handle_oom(now, 1000);
     292           1 :   tt_size_op(bytes_removed, OP_GT, 0);
     293             : 
     294             :   /* Do it again but this time with an entry with a lower cutoff. */
     295           1 :   geoip_entry_stats_init(now);
     296           1 :   SET_TEST_ADDRESS(100);
     297           1 :   geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL,
     298             :                          now - (3 * 60 * 60));
     299           1 :   bytes_removed = geoip_client_cache_handle_oom(now, 1000);
     300           1 :   tt_size_op(bytes_removed, OP_EQ, 0);
     301             : 
     302             :   /* Stop collecting entry statistics. */
     303           1 :   geoip_entry_stats_term();
     304           1 :   get_options_mutable()->EntryStatistics = 0;
     305             : 
     306           1 :  done:
     307           1 :   tor_free(s);
     308           1 :   tor_free(v);
     309           1 : }
     310             : 
     311             : static void
     312           1 : test_geoip_with_pt(void *arg)
     313             : {
     314           1 :   time_t now = 1281533250; /* 2010-08-11 13:27:30 UTC */
     315           1 :   char *s = NULL;
     316           1 :   int i;
     317           1 :   tor_addr_t addr;
     318           1 :   struct in6_addr in6;
     319             : 
     320           1 :   (void)arg;
     321           1 :   get_options_mutable()->BridgeRelay = 1;
     322           1 :   get_options_mutable()->BridgeRecordUsageByCountry = 1;
     323             : 
     324           1 :   memset(&in6, 0, sizeof(in6));
     325             : 
     326             :   /* No clients seen yet. */
     327           1 :   s = geoip_get_transport_history();
     328           1 :   tor_assert(!s);
     329             : 
     330             :   /* 4 connections without a pluggable transport */
     331           5 :   for (i=0; i < 4; ++i) {
     332           4 :     SET_TEST_ADDRESS(i);
     333           4 :     geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, NULL, now-7200);
     334             :   }
     335             : 
     336             :   /* 9 connections with "alpha" */
     337          10 :   for (i=4; i < 13; ++i) {
     338           9 :     SET_TEST_ADDRESS(i);
     339           9 :     geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "alpha", now-7200);
     340             :   }
     341             : 
     342             :   /* one connection with "beta" */
     343           1 :   SET_TEST_ADDRESS(13);
     344           1 :   geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "beta", now-7200);
     345             : 
     346             :   /* 14 connections with "charlie" */
     347          16 :   for (i=14; i < 28; ++i) {
     348          14 :     SET_TEST_ADDRESS(i);
     349          14 :     geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "charlie", now-7200);
     350             :   }
     351             : 
     352             :   /* 131 connections with "ddr" */
     353         132 :   for (i=28; i < 159; ++i) {
     354         131 :     SET_TEST_ADDRESS(i);
     355         131 :     geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "ddr", now-7200);
     356             :   }
     357             : 
     358             :   /* 8 connections with "entropy" */
     359           9 :   for (i=159; i < 167; ++i) {
     360           8 :     SET_TEST_ADDRESS(i);
     361           8 :     geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "entropy", now-7200);
     362             :   }
     363             : 
     364             :   /* 2 connections from the same IP with two different transports. */
     365           1 :   SET_TEST_ADDRESS(++i);
     366           1 :   geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "fire", now-7200);
     367           1 :   geoip_note_client_seen(GEOIP_CLIENT_CONNECT, &addr, "google", now-7200);
     368             : 
     369             :   /* Test the transport history string. */
     370           1 :   s = geoip_get_transport_history();
     371           1 :   tor_assert(s);
     372           1 :   tt_str_op(s,OP_EQ, "<OR>=8,alpha=16,beta=8,charlie=16,ddr=136,"
     373             :              "entropy=8,fire=8,google=8");
     374             : 
     375             :   /* Stop collecting entry statistics. */
     376           1 :   geoip_entry_stats_term();
     377           1 :   get_options_mutable()->EntryStatistics = 0;
     378             : 
     379           1 :  done:
     380           1 :   tor_free(s);
     381           1 : }
     382             : 
     383             : #undef SET_TEST_ADDRESS
     384             : #undef SET_TEST_IPV6
     385             : #undef CHECK_COUNTRY
     386             : 
     387             : static const char GEOIP_CONTENT[] =
     388             :   "134445936,134445939,MP\n"
     389             :   "134445940,134447103,GU\n"
     390             :   "134447104,134738943,US\n"
     391             :   "134738944,134739199,CA\n"
     392             :   "134739200,135192575,US\n"
     393             :   "135192576,135200767,MX\n"
     394             :   "135200768,135430143,US\n"
     395             :   "135430144,135430399,CA\n"
     396             :   "135430400,135432191,US\n";
     397             : 
     398             : static void
     399           1 : test_geoip_load_file(void *arg)
     400             : {
     401           1 :   (void)arg;
     402           1 :   char *contents = NULL;
     403           1 :   char *dhex = NULL;
     404             : 
     405             :   /* A nonexistent filename should fail. */
     406           1 :   tt_int_op(-1, OP_EQ,
     407             :             geoip_load_file(AF_INET, "/you/did/not/put/a/file/here/I/hope",
     408             :                             LOG_INFO));
     409             : 
     410             :   /* We start out with only "Ningunpartia" in the database. */
     411           1 :   tt_int_op(1, OP_EQ, geoip_get_n_countries());
     412           1 :   tt_str_op("??", OP_EQ, geoip_get_country_name(0));
     413             :   /* Any lookup attempt should say "-1" because we have no info */
     414           1 :   tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv4(0x01020304));
     415             :   /* There should be no 'digest' for a nonexistent file */
     416           1 :   tt_str_op("0000000000000000000000000000000000000000", OP_EQ,
     417             :             geoip_db_digest(AF_INET));
     418             : 
     419           1 :   const char *fname = get_fname("geoip");
     420           1 :   tt_int_op(0, OP_EQ, write_str_to_file(fname, GEOIP_CONTENT, 1));
     421             : 
     422           1 :   int rv = geoip_load_file(AF_INET, fname, LOG_WARN);
     423           1 :   if (rv != 0) {
     424           0 :     TT_GRIPE(("Unable to load geoip from %s", escaped(fname)));
     425             :   }
     426           1 :   tt_int_op(0, OP_EQ, rv);
     427             : 
     428             :   /* Check that we loaded some countries; this will fail if there are ever
     429             :    * fewer than 5 countries in our test above. */
     430           1 :   tt_int_op(geoip_get_n_countries(), OP_GE, 5);
     431             : 
     432             :   /* Let's see where 8.8.8.8 is. */
     433           1 :   int country = geoip_get_country_by_ipv4(0x08080808);
     434           1 :   tt_int_op(country, OP_GE, 1); /* It shouldn't be 'unknown' or 'nowhere' */
     435           1 :   const char *cc = geoip_get_country_name(country);
     436           1 :   tt_int_op(strlen(cc), OP_EQ, 2);
     437             : 
     438             :   /* The digest should be set.... */
     439           1 :   tt_str_op("0000000000000000000000000000000000000000", OP_NE,
     440             :             geoip_db_digest(AF_INET));
     441             : 
     442             :   /* And it should be set correctly */
     443           1 :   contents = read_file_to_str(fname, RFTS_BIN, NULL);
     444           1 :   uint8_t d[DIGEST_LEN];
     445           1 :   crypto_digest((char*)d, contents, strlen(contents));
     446           1 :   dhex = tor_strdup(hex_str((char*)d, DIGEST_LEN));
     447           1 :   tt_str_op(dhex, OP_EQ, geoip_db_digest(AF_INET));
     448             : 
     449             :   /* Make sure geoip_free_all() works. */
     450           1 :   geoip_free_all();
     451           1 :   tt_int_op(1, OP_EQ, geoip_get_n_countries());
     452           1 :   tt_str_op("??", OP_EQ, geoip_get_country_name(0));
     453           1 :   tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv4(0x01020304));
     454           1 :   tt_str_op("0000000000000000000000000000000000000000", OP_EQ,
     455             :             geoip_db_digest(AF_INET)); // <--- nick bets this will fail.
     456             : 
     457           1 :  done:
     458           1 :   tor_free(contents);
     459           1 :   tor_free(dhex);
     460           1 : }
     461             : 
     462             : static void
     463           1 : test_geoip6_load_file(void *arg)
     464             : {
     465           1 :   (void)arg;
     466           1 :   struct in6_addr iaddr6;
     467           1 :   char *contents = NULL;
     468           1 :   char *dhex = NULL;
     469             : 
     470             :   /* A nonexistent filename should fail. */
     471           1 :   tt_int_op(-1, OP_EQ,
     472             :             geoip_load_file(AF_INET6, "/you/did/not/put/a/file/here/I/hope",
     473             :                             LOG_INFO));
     474             : 
     475             :   /* Any lookup attempt should say "-1" because we have no info */
     476           1 :   tor_inet_pton(AF_INET6, "2001:4860:4860::8888", &iaddr6);
     477           1 :   tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv6(&iaddr6));
     478             : 
     479             :   /* Load geiop6 file */
     480           1 :   const char *fname6 = get_fname("geoip6");
     481           1 :   const char CONTENT[] =
     482             :     "2001:4830:6010::,2001:4830:601f:ffff:ffff:ffff:ffff:ffff,GB\n"
     483             :     "2001:4830:6020::,2001:4830:ffff:ffff:ffff:ffff:ffff:ffff,US\n"
     484             :     "2001:4838::,2001:4838:ffff:ffff:ffff:ffff:ffff:ffff,US\n"
     485             :     "2001:4840::,2001:4840:ffff:ffff:ffff:ffff:ffff:ffff,XY\n"
     486             :     "2001:4848::,2001:4848:ffff:ffff:ffff:ffff:ffff:ffff,ZD\n"
     487             :     "2001:4850::,2001:4850:ffff:ffff:ffff:ffff:ffff:ffff,RO\n"
     488             :     "2001:4858::,2001:4858:ffff:ffff:ffff:ffff:ffff:ffff,TC\n"
     489             :     "2001:4860::,2001:4860:ffff:ffff:ffff:ffff:ffff:ffff,US\n"
     490             :     "2001:4868::,2001:4868:ffff:ffff:ffff:ffff:ffff:ffff,US\n"
     491             :     "2001:4870::,2001:4871:ffff:ffff:ffff:ffff:ffff:ffff,NB\n"
     492             :     "2001:4878::,2001:4878:128:ffff:ffff:ffff:ffff:ffff,US\n"
     493             :     "2001:4878:129::,2001:4878:129:ffff:ffff:ffff:ffff:ffff,CR\n"
     494             :     "2001:4878:12a::,2001:4878:203:ffff:ffff:ffff:ffff:ffff,US\n"
     495             :     "2001:4878:204::,2001:4878:204:ffff:ffff:ffff:ffff:ffff,DE\n"
     496             :     "2001:4878:205::,2001:4878:214:ffff:ffff:ffff:ffff:ffff,US\n";
     497           1 :   tt_int_op(0, OP_EQ, write_str_to_file(fname6, CONTENT, 1));
     498             : 
     499           1 :   tt_int_op(0, OP_EQ, geoip_load_file(AF_INET6, fname6, LOG_WARN));
     500             : 
     501             :   /* Check that we loaded some countries; this will fail if there are ever
     502             :    * fewer than 5 countries in our test data above. */
     503           1 :   tt_int_op(geoip_get_n_countries(), OP_GE, 5);
     504             : 
     505             :   /* Let's see where 2001:4860:4860::8888 (google dns) is. */
     506           1 :   const char *caddr6 = "2001:4860:4860::8888";
     507           1 :   tor_inet_pton(AF_INET6, caddr6, &iaddr6);
     508           1 :   int country6 = geoip_get_country_by_ipv6(&iaddr6);
     509           1 :   tt_int_op(country6, OP_GE, 1);
     510             : 
     511           1 :   const char *cc6 = geoip_get_country_name(country6);
     512           1 :   tt_int_op(strlen(cc6), OP_EQ, 2);
     513             : 
     514             :   /* The digest should be set.... */
     515           1 :   tt_str_op("0000000000000000000000000000000000000000", OP_NE,
     516             :             geoip_db_digest(AF_INET6));
     517             : 
     518             :   /* And it should be set correctly */
     519           1 :   contents = read_file_to_str(fname6, RFTS_BIN, NULL);
     520           1 :   uint8_t d[DIGEST_LEN];
     521           1 :   crypto_digest((char*)d, contents, strlen(contents));
     522           1 :   dhex = tor_strdup(hex_str((char*)d, DIGEST_LEN));
     523           1 :   tt_str_op(dhex, OP_EQ, geoip_db_digest(AF_INET6));
     524             : 
     525             :   /* Make sure geoip_free_all() works. */
     526           1 :   geoip_free_all();
     527           1 :   tt_int_op(1, OP_EQ, geoip_get_n_countries());
     528           1 :   tt_str_op("??", OP_EQ, geoip_get_country_name(0));
     529           1 :   tor_inet_pton(AF_INET6, "::1:2:3:4", &iaddr6);
     530           1 :   tt_int_op(-1, OP_EQ, geoip_get_country_by_ipv6(&iaddr6));
     531           1 :   tt_str_op("0000000000000000000000000000000000000000", OP_EQ,
     532             :             geoip_db_digest(AF_INET6));
     533             : 
     534           1 :  done:
     535           1 :   tor_free(contents);
     536           1 :   tor_free(dhex);
     537           1 : }
     538             : 
     539             : static void
     540           1 : test_geoip_load_2nd_file(void *arg)
     541             : {
     542           1 :   (void)arg;
     543             : 
     544           1 :   char *fname_geoip = tor_strdup(get_fname("geoip_data"));
     545           1 :   char *fname_empty = tor_strdup(get_fname("geoip_empty"));
     546             : 
     547           1 :   tt_int_op(0, OP_EQ, write_str_to_file(fname_geoip, GEOIP_CONTENT, 1));
     548           1 :   tt_int_op(0, OP_EQ, write_str_to_file(fname_empty, "\n", 1));
     549             : 
     550             :   /* Load 1st geoip file */
     551           1 :   tt_int_op(0, OP_EQ, geoip_load_file(AF_INET, fname_geoip, LOG_WARN));
     552             : 
     553             :   /* Load 2nd geoip (empty) file */
     554             :   /* It has to be the same IP address family */
     555           1 :   tt_int_op(0, OP_EQ, geoip_load_file(AF_INET, fname_empty, LOG_WARN));
     556             : 
     557             :   /* Check that there is no geoip information for 8.8.8.8, */
     558             :   /* since loading the empty 2nd file should have delete it. */
     559           1 :   int country = geoip_get_country_by_ipv4(0x08080808);
     560           1 :   tt_int_op(country, OP_EQ, 0);
     561             : 
     562           1 :  done:
     563           1 :   tor_free(fname_geoip);
     564           1 :   tor_free(fname_empty);
     565           1 : }
     566             : 
     567             : #define ENT(name)                                                       \
     568             :   { #name, test_ ## name , 0, NULL, NULL }
     569             : #define FORK(name)                                                      \
     570             :   { #name, test_ ## name , TT_FORK, NULL, NULL }
     571             : 
     572             : struct testcase_t geoip_tests[] = {
     573             :   { "geoip", test_geoip, TT_FORK, NULL, NULL },
     574             :   { "geoip_with_pt", test_geoip_with_pt, TT_FORK, NULL, NULL },
     575             :   { "load_file", test_geoip_load_file, TT_FORK, NULL, NULL },
     576             :   { "load_file6", test_geoip6_load_file, TT_FORK, NULL, NULL },
     577             :   { "load_2nd_file", test_geoip_load_2nd_file, TT_FORK, NULL, NULL },
     578             : 
     579             :   END_OF_TESTCASES
     580             : };

Generated by: LCOV version 1.14