This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git


The following commit(s) were added to refs/heads/master by this push:
     new c2073a92d testing/libc/inetntop: Add a test of inet_ntop().
c2073a92d is described below

commit c2073a92d744bbde7f6f7579d52949ad08f77d19
Author: Marco Casaroli <[email protected]>
AuthorDate: Wed Nov 11 08:20:01 2026 +0100

    testing/libc/inetntop: Add a test of inet_ntop().
    
    No test in nuttx-apps checks inet_ntop().  This test converts IPv6
    addresses with inet_ntop(AF_INET6) and compares the text with the
    recommended form of RFC 5952: "::" only for the longest run of two or
    more 0 fields (the first one on a tie), no "::" for one 0 field, and
    lowercase hexadecimal.  The IPv4-mapped address (::ffff:127.0.0.1) and
    the IPv4-compatible address (::1.2.3.4) end in the dotted-decimal form;
    :: and ::1 do not.  glibc gives the same text for each case.
    
    Each case also checks the size of the buffer, for AF_INET6 and AF_INET:
    the call succeeds with strlen() + 1 bytes and fails with ENOSPC with
    strlen() bytes.
    
    The program prints PASS or FAIL for each case and returns the number of
    errors.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 testing/libc/inetntop/CMakeLists.txt  |  35 +++++
 testing/libc/inetntop/Kconfig         |  34 +++++
 testing/libc/inetntop/Make.defs       |  25 ++++
 testing/libc/inetntop/Makefile        |  36 +++++
 testing/libc/inetntop/inetntop_main.c | 255 ++++++++++++++++++++++++++++++++++
 5 files changed, 385 insertions(+)

diff --git a/testing/libc/inetntop/CMakeLists.txt 
b/testing/libc/inetntop/CMakeLists.txt
new file mode 100644
index 000000000..6103c6dfd
--- /dev/null
+++ b/testing/libc/inetntop/CMakeLists.txt
@@ -0,0 +1,35 @@
+# 
##############################################################################
+# apps/testing/libc/inetntop/CMakeLists.txt
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more 
contributor
+# license agreements.  See the NOTICE file distributed with this work for
+# additional information regarding copyright ownership.  The ASF licenses this
+# file to you under the Apache License, Version 2.0 (the "License"); you may 
not
+# use this file except in compliance with the License.  You may obtain a copy 
of
+# the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations under
+# the License.
+#
+# 
##############################################################################
+
+if(CONFIG_TESTING_INETNTOP)
+  nuttx_add_application(
+    NAME
+    ${CONFIG_TESTING_INETNTOP_PROGNAME}
+    PRIORITY
+    ${CONFIG_TESTING_INETNTOP_PRIORITY}
+    STACKSIZE
+    ${CONFIG_TESTING_INETNTOP_STACKSIZE}
+    MODULE
+    ${CONFIG_TESTING_INETNTOP}
+    SRCS
+    inetntop_main.c)
+endif()
diff --git a/testing/libc/inetntop/Kconfig b/testing/libc/inetntop/Kconfig
new file mode 100644
index 000000000..3033aa262
--- /dev/null
+++ b/testing/libc/inetntop/Kconfig
@@ -0,0 +1,34 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+config TESTING_INETNTOP
+       tristate "inet_ntop() test"
+       default n
+       depends on (NET_IPv4 || LIBC_IPv4_ADDRCONV) && (NET_IPv6 || 
LIBC_IPv6_ADDRCONV)
+       ---help---
+               Check the text that inet_ntop(AF_INET6) makes: "::" only for the
+               longest run of two or more 0 fields, lowercase hexadecimal, and 
the
+               IPv4 dotted-decimal form for the IPv4-mapped and IPv4-compatible
+               addresses.  Also check that inet_ntop() fails with ENOSPC only 
when
+               the text does not fit in the buffer, for AF_INET6 and AF_INET.
+
+if TESTING_INETNTOP
+
+config TESTING_INETNTOP_PROGNAME
+       string "Program name"
+       default "inetntop"
+       ---help---
+               This is the name of the program that will be used when the NSH 
ELF
+               program is installed.
+
+config TESTING_INETNTOP_PRIORITY
+       int "inetntop task priority"
+       default 100
+
+config TESTING_INETNTOP_STACKSIZE
+       int "inetntop stack size"
+       default DEFAULT_TASK_STACKSIZE
+
+endif
diff --git a/testing/libc/inetntop/Make.defs b/testing/libc/inetntop/Make.defs
new file mode 100644
index 000000000..56aa0ba2d
--- /dev/null
+++ b/testing/libc/inetntop/Make.defs
@@ -0,0 +1,25 @@
+############################################################################
+# apps/testing/libc/inetntop/Make.defs
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+ifneq ($(CONFIG_TESTING_INETNTOP),)
+CONFIGURED_APPS += $(APPDIR)/testing/libc/inetntop
+endif
diff --git a/testing/libc/inetntop/Makefile b/testing/libc/inetntop/Makefile
new file mode 100644
index 000000000..f49e946b6
--- /dev/null
+++ b/testing/libc/inetntop/Makefile
@@ -0,0 +1,36 @@
+############################################################################
+# apps/testing/libc/inetntop/Makefile
+#
+# SPDX-License-Identifier: Apache-2.0
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+include $(APPDIR)/Make.defs
+
+# inet_ntop() test built-in application info
+
+PROGNAME  = $(CONFIG_TESTING_INETNTOP_PROGNAME)
+PRIORITY  = $(CONFIG_TESTING_INETNTOP_PRIORITY)
+STACKSIZE = $(CONFIG_TESTING_INETNTOP_STACKSIZE)
+MODULE    = $(CONFIG_TESTING_INETNTOP)
+
+# inet_ntop() test files
+
+MAINSRC = inetntop_main.c
+
+include $(APPDIR)/Application.mk
diff --git a/testing/libc/inetntop/inetntop_main.c 
b/testing/libc/inetntop/inetntop_main.c
new file mode 100644
index 000000000..7d699f71e
--- /dev/null
+++ b/testing/libc/inetntop/inetntop_main.c
@@ -0,0 +1,255 @@
+/****************************************************************************
+ * apps/testing/libc/inetntop/inetntop_main.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct ntop_case_s
+{
+  uint16_t words[8];          /* The address, as eight 16-bit fields */
+  FAR const char *text;       /* The expected text */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/* Convert src with a buffer of size bytes.  The text must be expect, or
+ * the call must fail with ENOSPC if expect is NULL.  Return the number of
+ * errors: 0 or 1.
+ */
+
+static int check_size(int af, FAR const void *src, socklen_t size,
+                      FAR const char *expect, FAR const char *name)
+{
+  FAR const char *ret;
+  char buf[INET6_ADDRSTRLEN + 8];
+
+  memset(buf, 'X', sizeof(buf));
+  errno = 0;
+  ret = inet_ntop(af, src, buf, size);
+  if (expect != NULL && ret == buf && strcmp(buf, expect) == 0)
+    {
+      return 0;
+    }
+
+  if (expect == NULL && ret == NULL && errno == ENOSPC)
+    {
+      return 0;
+    }
+
+  printf("FAIL: %s, size %u: returned \"%s\", errno %d, expected \"%s\"\n",
+         name, size, ret != NULL ? buf : "NULL", errno,
+         expect != NULL ? expect : "ENOSPC");
+  return 1;
+}
+
+/* The text must fit in strlen() + 1 bytes and fail with ENOSPC in
+ * strlen() bytes.
+ */
+
+static int check(int af, FAR const void *src, FAR const char *expect)
+{
+  socklen_t len = strlen(expect);
+  int nerrors;
+
+  nerrors  = check_size(af, src, len + 1, expect, expect);
+  nerrors += check_size(af, src, len, NULL, expect);
+  nerrors += check_size(af, src, INET6_ADDRSTRLEN, expect, expect);
+  if (nerrors == 0)
+    {
+      printf("PASS: \"%s\"\n", expect);
+    }
+
+  return nerrors;
+}
+
+static int check_ipv6(FAR const struct ntop_case_s *tc)
+{
+  struct in6_addr addr;
+  int i;
+
+  for (i = 0; i < 8; i++)
+    {
+      addr.s6_addr[2 * i]     = tc->words[i] >> 8;
+      addr.s6_addr[2 * i + 1] = tc->words[i] & 0xff;
+    }
+
+  return check(AF_INET6, &addr, tc->text);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int main(int argc, FAR char *argv[])
+{
+  static const struct ntop_case_s cases[] =
+  {
+    /* No 0 field, and the longest text */
+
+    {
+      {1, 2, 3, 4, 5, 6, 7, 8}, "1:2:3:4:5:6:7:8"
+    },
+    {
+      {0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+      "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
+    },
+
+    /* "::" at the start, in the middle and at the end */
+
+    {
+      {0, 0, 0, 0, 0, 0, 0, 0}, "::"
+    },
+    {
+      {0, 0, 0, 0, 0, 0, 0, 1}, "::1"
+    },
+    {
+      {1, 0, 0, 0, 0, 0, 0, 0}, "1::"
+    },
+    {
+      {0xfe80, 0, 0, 0, 0, 0, 0xab, 1}, "fe80::ab:1"
+    },
+    {
+      {0x2001, 0xdb8, 0, 0, 0, 0xff00, 0x42, 0x8329},
+      "2001:db8::ff00:42:8329"
+    },
+
+    /* RFC 5952 4.2.2: one 0 field is not shortened */
+
+    {
+      {1, 0, 2, 3, 4, 5, 6, 7}, "1:0:2:3:4:5:6:7"
+    },
+    {
+      {0, 1, 2, 3, 4, 5, 6, 7}, "0:1:2:3:4:5:6:7"
+    },
+    {
+      {1, 2, 3, 4, 5, 6, 7, 0}, "1:2:3:4:5:6:7:0"
+    },
+    {
+      {0x2001, 0xdb8, 0, 1, 1, 1, 1, 1}, "2001:db8:0:1:1:1:1:1"
+    },
+
+    /* RFC 5952 4.2.3: the longest run, the first one on a tie */
+
+    {
+      {1, 0, 0, 2, 0, 0, 0, 3}, "1:0:0:2::3"
+    },
+    {
+      {1, 0, 0, 2, 0, 0, 3, 4}, "1::2:0:0:3:4"
+    },
+    {
+      {0x2001, 0xdb8, 0, 0, 1, 0, 0, 1}, "2001:db8::1:0:0:1"
+    },
+
+    /* RFC 5952 4.3: lowercase */
+
+    {
+      {0x2001, 0xdb8, 0xaaaa, 0xbbbb, 0xcccc, 0xdddd, 0xeeee, 0xaaaa},
+      "2001:db8:aaaa:bbbb:cccc:dddd:eeee:aaaa"
+    },
+
+    /* RFC 5952 5: IPv4-mapped and IPv4-compatible, but not :: and ::1 */
+
+    {
+      {0, 0, 0, 0, 0, 0xffff, 0x7f00, 1}, "::ffff:127.0.0.1"
+    },
+    {
+      {0, 0, 0, 0, 0, 0xffff, 0, 0}, "::ffff:0.0.0.0"
+    },
+    {
+      {0, 0, 0, 0, 0, 0xffff, 0xffff, 0xffff}, "::ffff:255.255.255.255"
+    },
+    {
+      {0, 0, 0, 0, 0, 0, 0x102, 0x304}, "::1.2.3.4"
+    },
+    {
+      {0, 0, 0, 0, 0, 0, 1, 0}, "::0.1.0.0"
+    },
+    {
+      {0, 0, 0, 0, 0, 0, 0, 0x102}, "::102"
+    },
+
+    /* Near forms that are not IPv4-mapped */
+
+    {
+      {0, 0, 0, 0, 0, 0xfffe, 0x102, 0x304}, "::fffe:102:304"
+    },
+    {
+      {1, 0, 0, 0, 0, 0xffff, 0x102, 0x304}, "1::ffff:102:304"
+    },
+    {
+      {0, 0, 0, 0, 0xffff, 0, 0x102, 0x304}, "::ffff:0:102:304"
+    },
+    {
+      {0x64, 0xff9b, 0, 0, 0, 0, 0xc000, 0x221}, "64:ff9b::c000:221"
+    },
+  };
+
+  static const uint8_t ipv4[][4] =
+  {
+    {0, 0, 0, 0},
+    {1, 2, 3, 4},
+    {192, 168, 10, 200},
+    {255, 255, 255, 255},
+  };
+
+  static const FAR char * const ipv4text[] =
+  {
+    "0.0.0.0", "1.2.3.4", "192.168.10.200", "255.255.255.255",
+  };
+
+  int nerrors = 0;
+  size_t i;
+
+  printf("inetntop: inet_ntop() test\n");
+
+  for (i = 0; i < nitems(cases); i++)
+    {
+      nerrors += check_ipv6(&cases[i]);
+    }
+
+  for (i = 0; i < nitems(ipv4); i++)
+    {
+      nerrors += check(AF_INET, ipv4[i], ipv4text[i]);
+    }
+
+  printf("inetntop: %zu cases, %d errors\n",
+         nitems(cases) + nitems(ipv4), nerrors);
+  return nerrors > 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}

Reply via email to