/* Tests for the support_format_* functions. Copyright (C) 2026 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include static void test_format_address_family (void) { support_check_nss ("AF_INET", "address_family", support_format_address_family (AF_INET), "INET"); support_check_nss ("AF_INET6", "address_family", support_format_address_family (AF_INET6), "INET6"); support_check_nss ("AF_LOCAL", "address_family", support_format_address_family (AF_LOCAL), "LOCAL"); support_check_nss ("AF_UNSPEC", "address_family", support_format_address_family (AF_UNSPEC), "UNSPEC"); support_check_nss ("unknown family", "address_family", support_format_address_family (12345), ""); } static void test_format_herrno (void) { support_check_nss ("HOST_NOT_FOUND", "herrno", support_format_herrno (HOST_NOT_FOUND), "HOST_NOT_FOUND"); support_check_nss ("NO_ADDRESS", "herrno", support_format_herrno (NO_ADDRESS), "NO_ADDRESS"); support_check_nss ("NO_RECOVERY", "herrno", support_format_herrno (NO_RECOVERY), "NO_RECOVERY"); support_check_nss ("TRY_AGAIN", "herrno", support_format_herrno (TRY_AGAIN), "TRY_AGAIN"); support_check_nss ("invalid herrno", "herrno", support_format_herrno (12345), "\n"); } static void test_format_passwd (void) { struct passwd p = { .pw_name = (char *) "testuser", .pw_passwd = (char *) "x", .pw_uid = 1000, .pw_gid = 1000, .pw_gecos = (char *) "Test User", .pw_dir = (char *) "/home/testuser", .pw_shell = (char *) "/bin/bash" }; support_check_nss ("passwd", "passwd", support_format_passwd (&p), "name: testuser\n" "passwd: x\n" "uid: 1000\n" "gid: 1000\n" "gecos: Test User\n" "dir: /home/testuser\n" "shell: /bin/bash\n"); } static void test_format_group (void) { char *members[] = { (char *) "user1", (char *) "user2", NULL }; struct group g = { .gr_name = (char *) "testgroup", .gr_passwd = (char *) "x", .gr_gid = 100, .gr_mem = members }; support_check_nss ("group with members", "group", support_format_group (&g), "name: testgroup\n" "passwd: x\n" "gid: 100\n" "member: user1\n" "member: user2\n"); char *no_members[] = { NULL }; struct group g_empty = { .gr_name = (char *) "emptygroup", .gr_passwd = (char *) "", .gr_gid = 200, .gr_mem = no_members }; support_check_nss ("group without members", "group", support_format_group (&g_empty), "name: emptygroup\n" "passwd: \n" "gid: 200\n"); } static void test_format_spwd (void) { struct spwd s = { .sp_namp = (char *) "testuser", .sp_pwdp = (char *) "$6$rounds=5000$hash", .sp_lstchg = 19000, .sp_min = 0, .sp_max = 99999, .sp_warn = 7, .sp_inact = -1, .sp_expire = -1, .sp_flag = 0 }; support_check_nss ("spwd", "spwd", support_format_spwd (&s), "sp_namp: testuser\n" "sp_pwdp: $6$rounds=5000$hash\n" "sp_lstchg: 19000\n" "sp_min: 0\n" "sp_max: 99999\n" "sp_warn: 7\n" "sp_inact: -1\n" "sp_expire: -1\n" "sp_flag: 0\n"); } static void test_format_sgrp (void) { char *admins[] = { (char *) "admin1", NULL }; char *members[] = { (char *) "user1", (char *) "user2", NULL }; struct sgrp s = { .sg_namp = (char *) "testgroup", .sg_passwd = (char *) "!", .sg_adm = admins, .sg_mem = members }; support_check_nss ("sgrp", "sgrp", support_format_sgrp (&s), "name: testgroup\n" "passwd: !\n" "admin: admin1\n" "member: user1\n" "member: user2\n"); char *no_admins[] = { NULL }; char *no_members[] = { NULL }; struct sgrp s_empty = { .sg_namp = (char *) "emptygroup", .sg_passwd = (char *) "", .sg_adm = no_admins, .sg_mem = no_members }; support_check_nss ("sgrp empty", "sgrp", support_format_sgrp (&s_empty), "name: emptygroup\n" "passwd: \n"); } static void test_format_protoent (void) { char *aliases[] = { (char *) "ICMP", NULL }; struct protoent p = { .p_name = (char *) "icmp", .p_aliases = aliases, .p_proto = 1 }; support_check_nss ("protoent with alias", "protoent", support_format_protoent (&p), "name: icmp\n" "alias: ICMP\n" "proto: 1\n"); char *no_aliases[] = { NULL }; struct protoent p_no_alias = { .p_name = (char *) "tcp", .p_aliases = no_aliases, .p_proto = 6 }; support_check_nss ("protoent without alias", "protoent", support_format_protoent (&p_no_alias), "name: tcp\n" "proto: 6\n"); } static void test_format_servent (void) { char *aliases[] = { (char *) "WWW", (char *) "www-http", NULL }; struct servent s = { .s_name = (char *) "http", .s_aliases = aliases, .s_port = htons (80), .s_proto = (char *) "tcp" }; support_check_nss ("servent", "servent", support_format_servent (&s), "name: http\n" "alias: WWW\n" "alias: www-http\n" "port: 80\n" "proto: tcp\n"); } static void test_format_rpcent (void) { char *aliases[] = { (char *) "portmap", (char *) "sunrpc", NULL }; struct rpcent r = { .r_name = (char *) "portmapper", .r_aliases = aliases, .r_number = 100000 }; support_check_nss ("rpcent", "rpcent", support_format_rpcent (&r), "name: portmapper\n" "number: 100000\n" "alias: portmap\n" "alias: sunrpc\n"); } static void test_format_aliasent (void) { char *members[] = { (char *) "user1@example.com", (char *) "user2@example.com" }; struct aliasent a = { .alias_name = (char *) "staff", .alias_members_len = 2, .alias_members = members, .alias_local = 0 }; support_check_nss ("aliasent", "aliasent", support_format_aliasent (&a), "name: staff\n" "member: user1@example.com\n" "member: user2@example.com\n" "local: 0\n"); } static void test_format_ether_addr (void) { struct ether_addr e = { { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 } }; support_check_nss ("ether_addr", "ether_addr", support_format_ether_addr (&e), "address: 0:11:22:33:44:55\n"); } static void test_format_hostent (void) { char addr1[4] = { 192, 0, 2, 1 }; char addr2[4] = { 192, 0, 2, 2 }; char *addr_list[] = { addr1, addr2, NULL }; char *aliases[] = { (char *) "www.example", NULL }; struct hostent h = { .h_name = (char *) "example.com", .h_aliases = aliases, .h_addrtype = AF_INET, .h_length = 4, .h_addr_list = addr_list }; support_check_nss ("hostent IPv4", "hostent", support_format_hostent (&h), "name: example.com\n" "alias: www.example\n" "address: 192.0.2.1\n" "address: 192.0.2.2\n"); char addr6[16] = { 0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; char *addr6_list[] = { addr6, NULL }; char *no_aliases[] = { NULL }; struct hostent h6 = { .h_name = (char *) "ipv6.example.com", .h_aliases = no_aliases, .h_addrtype = AF_INET6, .h_length = 16, .h_addr_list = addr6_list }; support_check_nss ("hostent IPv6", "hostent", support_format_hostent (&h6), "name: ipv6.example.com\n" "address: 2001:db8::1\n"); } static void test_format_netent (void) { char *aliases[] = { (char *) "localnet", NULL }; struct netent n = { .n_name = (char *) "loopback", .n_aliases = aliases, .n_addrtype = AF_INET, .n_net = 0x7f000000 }; support_check_nss ("netent", "netent", support_format_netent (&n), "name: loopback\n" "alias: localnet\n" "net: 0x7f000000\n"); } static void test_format_addrinfo (void) { /* Test successful result with IPv4 address. */ struct sockaddr_in sin = { .sin_family = AF_INET, .sin_port = htons (80), .sin_addr = { htonl (0xc0000201) } /* 192.0.2.1 */ }; struct addrinfo ai = { .ai_flags = 0, .ai_family = AF_INET, .ai_socktype = SOCK_STREAM, .ai_protocol = IPPROTO_TCP, .ai_addrlen = sizeof (sin), .ai_addr = (struct sockaddr *) &sin, .ai_canonname = NULL, .ai_next = NULL }; support_check_nss ("addrinfo IPv4 STREAM/TCP", "addrinfo", support_format_addrinfo (&ai, 0), "address: STREAM/TCP 192.0.2.1 80\n"); /* Test with canonname. */ struct addrinfo ai_canon = { .ai_flags = AI_CANONNAME, .ai_family = AF_INET, .ai_socktype = SOCK_DGRAM, .ai_protocol = IPPROTO_UDP, .ai_addrlen = sizeof (sin), .ai_addr = (struct sockaddr *) &sin, .ai_canonname = (char *) "canonical.example.com", .ai_next = NULL }; support_check_nss ("addrinfo with canonname", "addrinfo", support_format_addrinfo (&ai_canon, 0), "flags: AI_CANONNAME\n" "canonname: canonical.example.com\n" "address: DGRAM/UDP 192.0.2.1 80\n"); /* Test error case. */ support_check_nss ("addrinfo EAI_NONAME", "addrinfo", support_format_addrinfo (NULL, EAI_NONAME), "error: Name or service not known\n"); } static int do_test (void) { test_format_address_family (); test_format_herrno (); test_format_passwd (); test_format_group (); test_format_spwd (); test_format_sgrp (); test_format_protoent (); test_format_servent (); test_format_rpcent (); test_format_aliasent (); test_format_ether_addr (); test_format_hostent (); test_format_netent (); test_format_addrinfo (); return 0; } #include