1 /* $OpenBSD: test_iterate.c,v 1.6 2018/07/16 03:09:59 djm Exp $ */
3 * Regress test for hostfile.h hostkeys_foreach()
5 * Placed in the public domain
10 #include <sys/types.h>
11 #include <sys/param.h>
19 #include "../test_helper/test_helper.h"
26 const char *key_file; /* Path for key, NULL for none */
27 int no_parse_status; /* Expected status w/o key parsing */
28 int no_parse_keytype; /* Expected keytype w/o key parsing */
29 int match_host_p; /* Match 'prometheus.example.com' */
30 int match_host_s; /* Match 'sisyphus.example.com' */
31 int match_ipv4; /* Match '192.0.2.1' */
32 int match_ipv6; /* Match '2001:db8::1' */
33 int match_flags; /* Expected flags from match */
34 struct hostkey_foreach_line l; /* Expected line contents */
38 const struct expected *expected;
49 * hostkeys_foreach() iterator callback that verifies the line passed
50 * against an array of expected entries.
53 check(struct hostkey_foreach_line *l, void *_ctx)
55 struct cbctx *ctx = (struct cbctx *)_ctx;
56 const struct expected *expected;
57 int parse_key = (ctx->flags & HKF_WANT_PARSE_KEY) != 0;
58 const int matching = (ctx->flags & HKF_WANT_MATCH) != 0;
59 u_int expected_status, expected_match;
62 test_subtest_info("entry %zu/%zu, file line %ld",
63 ctx->i + 1, ctx->nexpected, l->linenum);
66 ASSERT_SIZE_T_LT(ctx->i, ctx->nexpected);
67 expected = ctx->expected + ctx->i++;
68 /* If we are matching host/IP then skip entries that don't */
71 if (ctx->match_host_p && expected->match_host_p)
73 if (ctx->match_host_s && expected->match_host_s)
75 if (ctx->match_ipv4 && expected->match_ipv4)
77 if (ctx->match_ipv6 && expected->match_ipv6)
80 expected_status = (parse_key || expected->no_parse_status < 0) ?
81 expected->l.status : (u_int)expected->no_parse_status;
82 expected_match = expected->l.match;
83 #define UPDATE_MATCH_STATUS(x) do { \
84 if (ctx->x && expected->x) { \
85 expected_match |= expected->x; \
86 if (expected_status == HKF_STATUS_OK) \
87 expected_status = HKF_STATUS_MATCHED; \
90 expected_keytype = (parse_key || expected->no_parse_keytype < 0) ?
91 expected->l.keytype : expected->no_parse_keytype;
93 #ifndef OPENSSL_HAS_ECC
94 if (expected->l.keytype == KEY_ECDSA ||
95 expected->no_parse_keytype == KEY_ECDSA) {
96 expected_status = HKF_STATUS_INVALID;
97 expected_keytype = KEY_UNSPEC;
102 UPDATE_MATCH_STATUS(match_host_p);
103 UPDATE_MATCH_STATUS(match_host_s);
104 UPDATE_MATCH_STATUS(match_ipv4);
105 UPDATE_MATCH_STATUS(match_ipv6);
107 ASSERT_PTR_NE(l->path, NULL); /* Don't care about path */
108 ASSERT_LONG_LONG_EQ(l->linenum, expected->l.linenum);
109 ASSERT_U_INT_EQ(l->status, expected_status);
110 ASSERT_U_INT_EQ(l->match, expected_match);
111 /* Not all test entries contain fulltext */
112 if (expected->l.line != NULL)
113 ASSERT_STRING_EQ(l->line, expected->l.line);
114 ASSERT_INT_EQ(l->marker, expected->l.marker);
115 /* XXX we skip hashed hostnames for now; implement checking */
116 if (expected->l.hosts != NULL)
117 ASSERT_STRING_EQ(l->hosts, expected->l.hosts);
118 /* Not all test entries contain raw keys */
119 if (expected->l.rawkey != NULL)
120 ASSERT_STRING_EQ(l->rawkey, expected->l.rawkey);
121 /* XXX synthesise raw key for cases lacking and compare */
122 ASSERT_INT_EQ(l->keytype, expected_keytype);
124 if (expected->l.key == NULL)
125 ASSERT_PTR_EQ(l->key, NULL);
126 if (expected->l.key != NULL) {
127 ASSERT_PTR_NE(l->key, NULL);
128 ASSERT_INT_EQ(sshkey_equal(l->key, expected->l.key), 1);
131 if (parse_key && !(l->comment == NULL && expected->l.comment == NULL))
132 ASSERT_STRING_EQ(l->comment, expected->l.comment);
136 /* Loads public keys for a set of expected results */
138 prepare_expected(struct expected *expected, size_t n)
142 for (i = 0; i < n; i++) {
143 if (expected[i].key_file == NULL)
145 #ifndef OPENSSL_HAS_ECC
146 if (expected[i].l.keytype == KEY_ECDSA)
149 ASSERT_INT_EQ(sshkey_load_public(
150 test_data_file(expected[i].key_file), &expected[i].l.key,
156 cleanup_expected(struct expected *expected, size_t n)
160 for (i = 0; i < n; i++) {
161 sshkey_free(expected[i].l.key);
162 expected[i].l.key = NULL;
166 struct expected expected_full[] = {
167 { NULL, -1, -1, 0, 0, 0, 0, -1, {
168 NULL, /* path, don't care */
170 HKF_STATUS_COMMENT, /* status */
172 "# Plain host keys, plain host names", /* full line, optional */
173 MRK_NONE, /* marker (CA / revoked) */
174 NULL, /* hosts text */
175 NULL, /* raw key, optional */
176 KEY_UNSPEC, /* key type */
177 NULL, /* deserialised key */
180 { "dsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
187 "sisyphus.example.com",
190 NULL, /* filled at runtime */
193 { "ecdsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
200 "sisyphus.example.com",
203 NULL, /* filled at runtime */
206 { "ed25519_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
213 "sisyphus.example.com",
216 NULL, /* filled at runtime */
219 { "rsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
226 "sisyphus.example.com",
229 NULL, /* filled at runtime */
232 { NULL, -1, -1, 0, 0, 0, 0, -1, {
245 { NULL, -1, -1, 0, 0, 0, 0, -1, {
250 "# Plain host keys, hostnames + addresses",
258 { "dsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
265 "prometheus.example.com,192.0.2.1,2001:db8::1",
268 NULL, /* filled at runtime */
271 { "ecdsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
278 "prometheus.example.com,192.0.2.1,2001:db8::1",
281 NULL, /* filled at runtime */
284 { "ed25519_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
291 "prometheus.example.com,192.0.2.1,2001:db8::1",
294 NULL, /* filled at runtime */
297 { "rsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
304 "prometheus.example.com,192.0.2.1,2001:db8::1",
307 NULL, /* filled at runtime */
310 { NULL, -1, -1, 0, 0, 0, 0, -1, {
323 { NULL, -1, -1, 0, 0, 0, 0, -1, {
328 "# Some hosts with wildcard names / IPs",
336 { "dsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
343 "*.example.com,192.0.2.*,2001:*",
346 NULL, /* filled at runtime */
349 { "ecdsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
356 "*.example.com,192.0.2.*,2001:*",
359 NULL, /* filled at runtime */
362 { "ed25519_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
369 "*.example.com,192.0.2.*,2001:*",
372 NULL, /* filled at runtime */
375 { "rsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
382 "*.example.com,192.0.2.*,2001:*",
385 NULL, /* filled at runtime */
388 { NULL, -1, -1, 0, 0, 0, 0, -1, {
401 { NULL, -1, -1, 0, 0, 0, 0, -1, {
406 "# Hashed hostname and address entries",
414 { "dsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
424 NULL, /* filled at runtime */
427 { "ecdsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
437 NULL, /* filled at runtime */
440 { "ed25519_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
450 NULL, /* filled at runtime */
453 { "rsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
463 NULL, /* filled at runtime */
466 { NULL, -1, -1, 0, 0, 0, 0, -1, {
480 * The next series have each key listed multiple times, as the
481 * hostname and addresses in the pre-hashed known_hosts are split
484 { "dsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
494 NULL, /* filled at runtime */
497 { "dsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
507 NULL, /* filled at runtime */
510 { "dsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
520 NULL, /* filled at runtime */
523 { "ecdsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
533 NULL, /* filled at runtime */
536 { "ecdsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
546 NULL, /* filled at runtime */
549 { "ecdsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
559 NULL, /* filled at runtime */
562 { "ed25519_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
572 NULL, /* filled at runtime */
575 { "ed25519_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
585 NULL, /* filled at runtime */
588 { "ed25519_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
598 NULL, /* filled at runtime */
601 { "rsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
611 NULL, /* filled at runtime */
614 { "rsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
624 NULL, /* filled at runtime */
627 { "rsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
637 NULL, /* filled at runtime */
640 { NULL, -1, -1, 0, 0, 0, 0, -1, {
653 { NULL, -1, -1, 0, 0, 0, 0, -1, {
666 { NULL, -1, -1, 0, 0, 0, 0, -1, {
671 "# Revoked and CA keys",
679 { "ed25519_4.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
686 "sisyphus.example.com",
689 NULL, /* filled at runtime */
692 { "ecdsa_4.pub" , -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, {
699 "prometheus.example.com",
702 NULL, /* filled at runtime */
705 { "dsa_4.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, 0, 0, -1, {
715 NULL, /* filled at runtime */
718 { NULL, -1, -1, 0, 0, 0, 0, -1, {
731 { NULL, -1, -1, 0, 0, 0, 0, -1, {
736 "# Some invalid lines",
744 { NULL, -1, -1, 0, 0, 0, 0, -1, {
757 { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
764 "sisyphus.example.com",
770 { NULL, -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, {
777 "prometheus.example.com",
783 { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
786 HKF_STATUS_INVALID, /* Would be ok if key not parsed */
790 "sisyphus.example.com",
796 { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
803 "sisyphus.example.com",
806 NULL, /* filled at runtime */
809 { NULL, HKF_STATUS_OK, KEY_RSA, HKF_MATCH_HOST, 0, 0, 0, -1, {
812 HKF_STATUS_INVALID, /* Would be ok if key not parsed */
816 "prometheus.example.com",
819 NULL, /* filled at runtime */
824 void test_iterate(void);
831 TEST_START("hostkeys_iterate all with key parse");
832 memset(&ctx, 0, sizeof(ctx));
833 ctx.expected = expected_full;
834 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
835 ctx.flags = HKF_WANT_PARSE_KEY;
836 prepare_expected(expected_full, ctx.nexpected);
837 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
838 check, &ctx, NULL, NULL, ctx.flags), 0);
839 cleanup_expected(expected_full, ctx.nexpected);
842 TEST_START("hostkeys_iterate all without key parse");
843 memset(&ctx, 0, sizeof(ctx));
844 ctx.expected = expected_full;
845 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
847 prepare_expected(expected_full, ctx.nexpected);
848 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
849 check, &ctx, NULL, NULL, ctx.flags), 0);
850 cleanup_expected(expected_full, ctx.nexpected);
853 TEST_START("hostkeys_iterate specify host 1");
854 memset(&ctx, 0, sizeof(ctx));
855 ctx.expected = expected_full;
856 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
858 ctx.match_host_p = 1;
859 prepare_expected(expected_full, ctx.nexpected);
860 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
861 check, &ctx, "prometheus.example.com", NULL, ctx.flags), 0);
862 cleanup_expected(expected_full, ctx.nexpected);
865 TEST_START("hostkeys_iterate specify host 2");
866 memset(&ctx, 0, sizeof(ctx));
867 ctx.expected = expected_full;
868 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
870 ctx.match_host_s = 1;
871 prepare_expected(expected_full, ctx.nexpected);
872 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
873 check, &ctx, "sisyphus.example.com", NULL, ctx.flags), 0);
874 cleanup_expected(expected_full, ctx.nexpected);
877 TEST_START("hostkeys_iterate match host 1");
878 memset(&ctx, 0, sizeof(ctx));
879 ctx.expected = expected_full;
880 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
881 ctx.flags = HKF_WANT_MATCH;
882 ctx.match_host_p = 1;
883 prepare_expected(expected_full, ctx.nexpected);
884 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
885 check, &ctx, "prometheus.example.com", NULL, ctx.flags), 0);
886 cleanup_expected(expected_full, ctx.nexpected);
889 TEST_START("hostkeys_iterate match host 2");
890 memset(&ctx, 0, sizeof(ctx));
891 ctx.expected = expected_full;
892 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
893 ctx.flags = HKF_WANT_MATCH;
894 ctx.match_host_s = 1;
895 prepare_expected(expected_full, ctx.nexpected);
896 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
897 check, &ctx, "sisyphus.example.com", NULL, ctx.flags), 0);
898 cleanup_expected(expected_full, ctx.nexpected);
901 TEST_START("hostkeys_iterate specify host missing");
902 memset(&ctx, 0, sizeof(ctx));
903 ctx.expected = expected_full;
904 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
906 prepare_expected(expected_full, ctx.nexpected);
907 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
908 check, &ctx, "actaeon.example.org", NULL, ctx.flags), 0);
909 cleanup_expected(expected_full, ctx.nexpected);
912 TEST_START("hostkeys_iterate match host missing");
913 memset(&ctx, 0, sizeof(ctx));
914 ctx.expected = expected_full;
915 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
916 ctx.flags = HKF_WANT_MATCH;
917 prepare_expected(expected_full, ctx.nexpected);
918 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
919 check, &ctx, "actaeon.example.org", NULL, ctx.flags), 0);
920 cleanup_expected(expected_full, ctx.nexpected);
923 TEST_START("hostkeys_iterate specify IPv4");
924 memset(&ctx, 0, sizeof(ctx));
925 ctx.expected = expected_full;
926 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
929 prepare_expected(expected_full, ctx.nexpected);
930 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
931 check, &ctx, "tiresias.example.org", "192.0.2.1", ctx.flags), 0);
932 cleanup_expected(expected_full, ctx.nexpected);
935 TEST_START("hostkeys_iterate specify IPv6");
936 memset(&ctx, 0, sizeof(ctx));
937 ctx.expected = expected_full;
938 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
941 prepare_expected(expected_full, ctx.nexpected);
942 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
943 check, &ctx, "tiresias.example.org", "2001:db8::1", ctx.flags), 0);
944 cleanup_expected(expected_full, ctx.nexpected);
947 TEST_START("hostkeys_iterate match IPv4");
948 memset(&ctx, 0, sizeof(ctx));
949 ctx.expected = expected_full;
950 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
951 ctx.flags = HKF_WANT_MATCH;
953 prepare_expected(expected_full, ctx.nexpected);
954 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
955 check, &ctx, "tiresias.example.org", "192.0.2.1", ctx.flags), 0);
956 cleanup_expected(expected_full, ctx.nexpected);
959 TEST_START("hostkeys_iterate match IPv6");
960 memset(&ctx, 0, sizeof(ctx));
961 ctx.expected = expected_full;
962 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
963 ctx.flags = HKF_WANT_MATCH;
965 prepare_expected(expected_full, ctx.nexpected);
966 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
967 check, &ctx, "tiresias.example.org", "2001:db8::1", ctx.flags), 0);
968 cleanup_expected(expected_full, ctx.nexpected);
971 TEST_START("hostkeys_iterate specify addr missing");
972 memset(&ctx, 0, sizeof(ctx));
973 ctx.expected = expected_full;
974 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
976 prepare_expected(expected_full, ctx.nexpected);
977 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
978 check, &ctx, "tiresias.example.org", "192.168.0.1", ctx.flags), 0);
979 cleanup_expected(expected_full, ctx.nexpected);
982 TEST_START("hostkeys_iterate match addr missing");
983 memset(&ctx, 0, sizeof(ctx));
984 ctx.expected = expected_full;
985 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
986 ctx.flags = HKF_WANT_MATCH;
987 prepare_expected(expected_full, ctx.nexpected);
988 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
989 check, &ctx, "tiresias.example.org", "::1", ctx.flags), 0);
990 cleanup_expected(expected_full, ctx.nexpected);
993 TEST_START("hostkeys_iterate specify host 2 and IPv4");
994 memset(&ctx, 0, sizeof(ctx));
995 ctx.expected = expected_full;
996 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
998 ctx.match_host_s = 1;
1000 prepare_expected(expected_full, ctx.nexpected);
1001 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1002 check, &ctx, "sisyphus.example.com", "192.0.2.1", ctx.flags), 0);
1003 cleanup_expected(expected_full, ctx.nexpected);
1006 TEST_START("hostkeys_iterate match host 1 and IPv6");
1007 memset(&ctx, 0, sizeof(ctx));
1008 ctx.expected = expected_full;
1009 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
1010 ctx.flags = HKF_WANT_MATCH;
1011 ctx.match_host_p = 1;
1013 prepare_expected(expected_full, ctx.nexpected);
1014 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1015 check, &ctx, "prometheus.example.com",
1016 "2001:db8::1", ctx.flags), 0);
1017 cleanup_expected(expected_full, ctx.nexpected);
1020 TEST_START("hostkeys_iterate specify host 2 and IPv4 w/ key parse");
1021 memset(&ctx, 0, sizeof(ctx));
1022 ctx.expected = expected_full;
1023 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
1024 ctx.flags = HKF_WANT_PARSE_KEY;
1025 ctx.match_host_s = 1;
1027 prepare_expected(expected_full, ctx.nexpected);
1028 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1029 check, &ctx, "sisyphus.example.com", "192.0.2.1", ctx.flags), 0);
1030 cleanup_expected(expected_full, ctx.nexpected);
1033 TEST_START("hostkeys_iterate match host 1 and IPv6 w/ key parse");
1034 memset(&ctx, 0, sizeof(ctx));
1035 ctx.expected = expected_full;
1036 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
1037 ctx.flags = HKF_WANT_MATCH|HKF_WANT_PARSE_KEY;
1038 ctx.match_host_p = 1;
1040 prepare_expected(expected_full, ctx.nexpected);
1041 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1042 check, &ctx, "prometheus.example.com",
1043 "2001:db8::1", ctx.flags), 0);
1044 cleanup_expected(expected_full, ctx.nexpected);