[libc-commits] [libc] [libc] created integration tests for newhdrgen (PR #97361)

via libc-commits libc-commits at lists.llvm.org
Tue Jul 2 13:52:19 PDT 2024


https://github.com/aaryanshukla updated https://github.com/llvm/llvm-project/pull/97361

>From efd4b95fab1be1a6c58d4a8379dde24bc516c58d Mon Sep 17 00:00:00 2001
From: Aaryan Shukla <aaryanshukla at google.com>
Date: Mon, 1 Jul 2024 22:55:42 +0000
Subject: [PATCH 1/6] [libc] created integration tests for hdrgen

- added sorting to script so C headers are outputted in alpha order
---
 libc/newhdrgen/tests/expected_output/string.h | 102 ++++++
 libc/newhdrgen/tests/input/string.h.def       |  18 ++
 libc/newhdrgen/tests/input/test_string.yaml   | 303 ++++++++++++++++++
 libc/newhdrgen/tests/test_integration.py      |  42 +++
 libc/newhdrgen/yaml_to_classes.py             |   6 +-
 5 files changed, 469 insertions(+), 2 deletions(-)
 create mode 100644 libc/newhdrgen/tests/expected_output/string.h
 create mode 100644 libc/newhdrgen/tests/input/string.h.def
 create mode 100644 libc/newhdrgen/tests/input/test_string.yaml
 create mode 100644 libc/newhdrgen/tests/test_integration.py

diff --git a/libc/newhdrgen/tests/expected_output/string.h b/libc/newhdrgen/tests/expected_output/string.h
new file mode 100644
index 0000000000000..4dcb693c353e4
--- /dev/null
+++ b/libc/newhdrgen/tests/expected_output/string.h
@@ -0,0 +1,102 @@
+//===-- C standard library header string.h --------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_STRING_H
+#define LLVM_LIBC_STRING_H
+
+#include "__llvm-libc-common.h"
+
+#include "llvm-libc-macros/null-macro.h"
+
+#include <llvm-libc-types/size_t.h>
+
+__BEGIN_C_DECLS
+
+void * memccpy(void *__restrict, const void *__restrict, int, size_t);
+
+void * memchr(const void *, int, size_t);
+
+int memcmp(const void *, const void *, size_t);
+
+void * memcpy(void *__restrict, const void *__restrict, size_t);
+
+void * memmem(const void *, size_t, const void *, size_t);
+
+void * memmove(void *, const void *, size_t);
+
+void * mempcpy(void *__restrict, const void *__restrict, size_t);
+
+void * memrchr(const void *, int, size_t);
+
+void * memset(void *, int, size_t);
+
+void * memset_explicit(void *, int, size_t);
+
+char * stpcpy(char *__restrict, const char *__restrict);
+
+char * stpncpy(char *__restrict, const char *__restrict, size_t);
+
+char * strcasestr(const char *, const char *);
+
+char * strcat(char *__restrict, const char *__restrict);
+
+char * strchr(const char *, int);
+
+char * strchrnul(const char *, int);
+
+int strcmp(const char *, const char *);
+
+int strcoll(const char *, const char *);
+
+char * strcpy(char *__restrict, const char *__restrict);
+
+size_t strcspn(const char *, const char *);
+
+char * strdup(const char *);
+
+char * strerror(int);
+
+char * strerror_r(int, char *, size_t);
+
+size_t strlcat(const char *__restrict, const char *__restrict, size_t);
+
+size_t strlcpy(const char *__restrict, const char *__restrict, size_t);
+
+size_t strlen(const char *);
+
+char * strncat(char *, const char *, size_t);
+
+int strncmp(const char *, const char *, size_t);
+
+char * strncpy(char *__restrict, const char *__restrict, size_t);
+
+char * strndup(const char *, size_t);
+
+size_t strnlen(const char *, size_t);
+
+char * strpbrk(const char *, const char *);
+
+char * strrchr(const char *, int);
+
+char * strsep(char * *__restrict, const char *__restrict);
+
+char * strsignal(int);
+
+size_t strspn(const char *, const char *);
+
+char * strstr(const char *, const char *);
+
+char * strtok(char *__restrict, const char *__restrict);
+
+char * strtok_r(char *__restrict, const char *__restrict, char * *__restrict);
+
+size_t strxfrm(char *__restrict, const char *__restrict, size_t);
+
+__END_C_DECLS
+
+#endif // LLVM_LIBC_STRING_H
diff --git a/libc/newhdrgen/tests/input/string.h.def b/libc/newhdrgen/tests/input/string.h.def
new file mode 100644
index 0000000000000..1bd2687db2bea
--- /dev/null
+++ b/libc/newhdrgen/tests/input/string.h.def
@@ -0,0 +1,18 @@
+//===-- C standard library header string.h --------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_STRING_H
+#define LLVM_LIBC_STRING_H
+
+#include "__llvm-libc-common.h"
+
+#include "llvm-libc-macros/null-macro.h"
+
+%%public_api()
+
+#endif // LLVM_LIBC_STRING_H
diff --git a/libc/newhdrgen/tests/input/test_string.yaml b/libc/newhdrgen/tests/input/test_string.yaml
new file mode 100644
index 0000000000000..2754f856bc807
--- /dev/null
+++ b/libc/newhdrgen/tests/input/test_string.yaml
@@ -0,0 +1,303 @@
+header: string.h
+macros: []
+types:
+  - type_name: size_t
+enums: []
+objects: []
+functions:
+  - name: memcpy
+    standards: 
+      - stdc
+    return_type: void *
+    arguments:
+      - type: void *__restrict
+      - type: const void *__restrict
+      - type: size_t
+  - name: memmove
+    standards: 
+      - stdc
+    return_type: void *
+    arguments:
+      - type: void *
+      - type: const void *
+      - type: size_t
+  - name: memcmp
+    standards: 
+      - stdc
+    return_type: int
+    arguments:
+      - type: const void *
+      - type: const void *
+      - type: size_t
+  - name: memchr
+    standards: 
+      - stdc
+    return_type: void *
+    arguments:
+      - type: const void *
+      - type: int
+      - type: size_t
+  - name: memset
+    standards: 
+      - stdc
+    return_type: void *
+    arguments:
+      - type: void *
+      - type: int
+      - type: size_t
+  - name: memset_explicit
+    standards: 
+      - stdc
+    return_type: void *
+    arguments:
+      - type: void *
+      - type: int
+      - type: size_t
+  - name: strcpy
+    standards: 
+      - stdc
+    return_type: char
+    arguments:
+      - type: char *__restrict
+      - type: const char *__restrict
+  - name: strncpy
+    standards: 
+      - stdc
+    return_type: char *
+    arguments:
+      - type: char *__restrict
+      - type: const char *__restrict
+      - type: size_t
+  - name: strcat
+    standards: 
+      - stdc
+    return_type: char *
+    arguments:
+      - type: char *__restrict
+      - type: const char *__restrict
+  - name: strncat
+    standards: 
+      - stdc
+    return_type: char *
+    arguments:
+      - type: char *
+      - type: const char *
+      - type: size_t
+  - name: strcmp
+    standards: 
+      - stdc
+    return_type: int
+    arguments:
+      - type: const char *
+      - type: const char *
+  - name: strcoll
+    standards: 
+      - stdc
+    return_type: int
+    arguments:
+      - type: const char *
+      - type: const char *
+  - name: strncmp
+    standards: 
+      - stdc
+    return_type: int
+    arguments:
+      - type: const char *
+      - type: const char *
+      - type: size_t
+  - name: strxfrm
+    standards: 
+      - stdc
+    return_type: size_t
+    arguments:
+      - type: char *__restrict
+      - type: const char *__restrict
+      - type: size_t
+  - name: strchr
+    standards: 
+      - stdc
+    return_type: char *
+    arguments:
+      - type: const char *
+      - type: int
+  - name: strcspn
+    standards: 
+      - stdc
+    return_type: size_t
+    arguments:
+      - type: const char *
+      - type: const char *
+  - name: strdup
+    return_type: char *
+    arguments:
+      - type: const char *
+  - name: strndup
+    standards: 
+      - stdc
+    return_type: char *
+    arguments:
+      - type: const char *
+      - type: size_t
+  - name: strpbrk
+    standards: 
+      - stdc
+    return_type: char *
+    arguments:
+      - type: const char *
+      - type: const char *
+  - name: strrchr
+    standards: 
+      - stdc
+    return_type: char *
+    arguments:
+      - type: const char *
+      - type: int
+  - name: strspn
+    standards: 
+      - stdc
+    return_type: size_t
+    arguments:
+      - type: const char *
+      - type: const char *
+  - name: strstr
+    standards: 
+      - stdc
+    return_type: char *
+    arguments:
+      - type: const char *
+      - type: const char *
+  - name: strtok
+    standards: 
+      - stdc
+    return_type: char *
+    arguments:
+      - type: char *__restrict
+      - type: const char *__restrict
+  - name: strerror
+    standards: 
+      - stdc
+    return_type: char *
+    arguments:
+      - type: int
+  - name: strlen
+    standards: 
+      - stdc
+    return_type: size_t
+    arguments:
+      - type: const char *
+  - name: memccpy
+    standards: 
+      - POSIX
+    return_type: void *
+    arguments:
+      - type: void *__restrict
+      - type: const void *__restrict
+      - type: int
+      - type: size_t
+  - name: mempcpy
+    standards: 
+      - POSIX
+    return_type: void *
+    arguments:
+      - type: void *__restrict
+      - type: const void *__restrict
+      - type: size_t
+  - name: stpcpy
+    standards: 
+      - POSIX
+    return_type: char *
+    arguments:
+      - type: char *__restrict
+      - type: const char *__restrict
+  - name: stpncpy
+    standards: 
+      - POSIX
+    return_type: char *
+    arguments:
+      - type: char *__restrict
+      - type: const char *__restrict
+      - type: size_t
+  - name: strnlen
+    standards: 
+      - POSIX
+    return_type: size_t
+    arguments:
+      - type: const char *
+      - type: size_t
+  - name: strtok_r
+    standards: 
+      - POSIX
+    return_type: char *
+    arguments:
+      - type: char *__restrict
+      - type: const char *__restrict
+      - type: char ** __restrict
+  - name: strsignal
+    standards: 
+      - POSIX
+    return_type: char *
+    arguments:
+      - type: int
+  - name: memmem
+    standards: 
+      - GNUExtensions
+    return_type: void *
+    arguments:
+      - type: const void *
+      - type: size_t
+      - type: const void *
+      - type: size_t
+  - name: memrchr
+    standards: 
+      - GNUExtensions
+    return_type: void *
+    arguments:
+      - type: const void *
+      - type: int
+      - type: size_t
+  - name: strerror_r
+    standards: 
+      - GNUExtensions
+    return_type: char *
+    arguments:
+      - type: int
+      - type: char *
+      - type: size_t
+  - name: strcasestr
+    standards: 
+      - GNUExtensions
+    return_type: char *
+    arguments:
+      - type: const char *
+      - type: const char *
+  - name: strchrnul
+    standards: 
+      - GNUExtensions
+    return_type: char *
+    arguments:
+      - type: const char *
+      - type: int
+  - name: strlcat
+    standards: 
+      - BSDExtensions
+    return_type: size_t
+    arguments:
+      - type: char *__restrict
+      - type: char *__restrict
+      - type: size_t
+  - name: strlcpy
+    standards: 
+      - BSDExtensions
+    return_type: size_t
+    arguments:
+      - type: char *__restrict
+      - type: char *__restrict
+      - type: size_t
+  - name: strsep
+    standards: 
+      - BSDExtensions
+    return_type: char *
+    arguments:
+      - type: char **__restrict
+      - type: char *__restrict
+
diff --git a/libc/newhdrgen/tests/test_integration.py b/libc/newhdrgen/tests/test_integration.py
new file mode 100644
index 0000000000000..ca485dc0377c1
--- /dev/null
+++ b/libc/newhdrgen/tests/test_integration.py
@@ -0,0 +1,42 @@
+import subprocess
+import unittest
+from pathlib import Path
+
+class TestHeaderGenIntegration(unittest.TestCase):
+    def setUp(self):
+        self.output_dir = Path('tests/output')
+        self.maxDiff = None  
+
+    def run_script(self, yaml_file, h_def_file, output_dir):
+        result = subprocess.run([
+            'python3', 'yaml_to_classes.py', yaml_file, h_def_file, '--output_dir', str(output_dir)
+        ], capture_output=True, text=True)
+
+        print("STDOUT:", result.stdout)
+        print("STDERR:", result.stderr)
+        result.check_returncode() 
+
+    def compare_files(self, generated_file, expected_file):
+        with generated_file.open('r') as gen_file:
+            gen_content = gen_file.read()
+        with expected_file.open('r') as exp_file:
+            exp_content = exp_file.read()
+        
+        self.assertEqual(gen_content, exp_content)
+
+    def test_generate_header(self):
+        # this is for example, will find a way to test everything at once
+        yaml_file = Path('tests/input/test_string.yaml')
+        h_def_file = Path('tests/input/string.h.def')
+        expected_output_file = Path('tests/expected_output/string.h')
+        output_file = self.output_dir / 'string.h'
+
+        if not self.output_dir.exists():
+            self.output_dir.mkdir(parents=True)
+
+        self.run_script(yaml_file, h_def_file, self.output_dir)
+
+        self.compare_files(output_file, expected_output_file)
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/libc/newhdrgen/yaml_to_classes.py b/libc/newhdrgen/yaml_to_classes.py
index 9b52c9cf9bb7c..65a990c8a8767 100644
--- a/libc/newhdrgen/yaml_to_classes.py
+++ b/libc/newhdrgen/yaml_to_classes.py
@@ -46,11 +46,13 @@ def yaml_to_classes(yaml_data):
             Enumeration(enum_data["name"], enum_data.get("value", None))
         )
 
-    for function_data in yaml_data.get("functions", []):
+    functions = yaml_data.get("functions", [])
+    sorted_functions = sorted(functions, key=lambda x: x['name'])
+    for function_data in sorted_functions:
         arguments = [arg["type"] for arg in function_data["arguments"]]
         guard = function_data.get("guard", None)
         attributes = function_data.get("attributes", None)
-        standards = (function_data.get("standards", None),)
+        standards = function_data.get("standards", None)
         header.add_function(
             Function(
                 function_data["return_type"],

>From f86c14bbf243b9d25daedbd0021ffa3b8058f7ea Mon Sep 17 00:00:00 2001
From: Aaryan Shukla <aaryanshukla at google.com>
Date: Mon, 1 Jul 2024 22:55:42 +0000
Subject: [PATCH 2/6] [libc] created integration tests for hdrgen

- added sorting to script so C headers are outputted in alpha order

>From 722a2eea3b11070b5436d1f402107cd76dbaab3d Mon Sep 17 00:00:00 2001
From: Aaryan Shukla <aaryanshukla at google.com>
Date: Mon, 1 Jul 2024 23:15:37 +0000
Subject: [PATCH 3/6] fixed formatting

---
 libc/newhdrgen/tests/test_integration.py | 39 +++++++++++++++---------
 libc/newhdrgen/yaml_to_classes.py        |  2 +-
 2 files changed, 26 insertions(+), 15 deletions(-)

diff --git a/libc/newhdrgen/tests/test_integration.py b/libc/newhdrgen/tests/test_integration.py
index ca485dc0377c1..1a942b461ad02 100644
--- a/libc/newhdrgen/tests/test_integration.py
+++ b/libc/newhdrgen/tests/test_integration.py
@@ -2,34 +2,44 @@
 import unittest
 from pathlib import Path
 
+
 class TestHeaderGenIntegration(unittest.TestCase):
     def setUp(self):
-        self.output_dir = Path('tests/output')
-        self.maxDiff = None  
+        self.output_dir = Path("tests/output")
+        self.maxDiff = None
 
     def run_script(self, yaml_file, h_def_file, output_dir):
-        result = subprocess.run([
-            'python3', 'yaml_to_classes.py', yaml_file, h_def_file, '--output_dir', str(output_dir)
-        ], capture_output=True, text=True)
+        result = subprocess.run(
+            [
+                "python3",
+                "yaml_to_classes.py",
+                yaml_file,
+                h_def_file,
+                "--output_dir",
+                str(output_dir),
+            ],
+            capture_output=True,
+            text=True,
+        )
 
         print("STDOUT:", result.stdout)
         print("STDERR:", result.stderr)
-        result.check_returncode() 
+        result.check_returncode()
 
     def compare_files(self, generated_file, expected_file):
-        with generated_file.open('r') as gen_file:
+        with generated_file.open("r") as gen_file:
             gen_content = gen_file.read()
-        with expected_file.open('r') as exp_file:
+        with expected_file.open("r") as exp_file:
             exp_content = exp_file.read()
-        
+
         self.assertEqual(gen_content, exp_content)
 
     def test_generate_header(self):
         # this is for example, will find a way to test everything at once
-        yaml_file = Path('tests/input/test_string.yaml')
-        h_def_file = Path('tests/input/string.h.def')
-        expected_output_file = Path('tests/expected_output/string.h')
-        output_file = self.output_dir / 'string.h'
+        yaml_file = Path("tests/input/test_string.yaml")
+        h_def_file = Path("tests/input/string.h.def")
+        expected_output_file = Path("tests/expected_output/string.h")
+        output_file = self.output_dir / "string.h"
 
         if not self.output_dir.exists():
             self.output_dir.mkdir(parents=True)
@@ -38,5 +48,6 @@ def test_generate_header(self):
 
         self.compare_files(output_file, expected_output_file)
 
-if __name__ == '__main__':
+
+if __name__ == "__main__":
     unittest.main()
diff --git a/libc/newhdrgen/yaml_to_classes.py b/libc/newhdrgen/yaml_to_classes.py
index 65a990c8a8767..e489c7f509b8e 100644
--- a/libc/newhdrgen/yaml_to_classes.py
+++ b/libc/newhdrgen/yaml_to_classes.py
@@ -47,7 +47,7 @@ def yaml_to_classes(yaml_data):
         )
 
     functions = yaml_data.get("functions", [])
-    sorted_functions = sorted(functions, key=lambda x: x['name'])
+    sorted_functions = sorted(functions, key=lambda x: x["name"])
     for function_data in sorted_functions:
         arguments = [arg["type"] for arg in function_data["arguments"]]
         guard = function_data.get("guard", None)

>From 62b6d624aaa7897bea05448548ea6039f8e6d06f Mon Sep 17 00:00:00 2001
From: Aaryan Shukla <aaryanshukla at google.com>
Date: Mon, 1 Jul 2024 23:21:39 +0000
Subject: [PATCH 4/6] clang formatter on string.h

---
 libc/newhdrgen/tests/expected_output/string.h | 58 +++++++++----------
 1 file changed, 29 insertions(+), 29 deletions(-)

diff --git a/libc/newhdrgen/tests/expected_output/string.h b/libc/newhdrgen/tests/expected_output/string.h
index 4dcb693c353e4..12ec66e4ff55b 100644
--- a/libc/newhdrgen/tests/expected_output/string.h
+++ b/libc/newhdrgen/tests/expected_output/string.h
@@ -17,51 +17,51 @@
 
 __BEGIN_C_DECLS
 
-void * memccpy(void *__restrict, const void *__restrict, int, size_t);
+void *memccpy(void *__restrict, const void *__restrict, int, size_t);
 
-void * memchr(const void *, int, size_t);
+void *memchr(const void *, int, size_t);
 
 int memcmp(const void *, const void *, size_t);
 
-void * memcpy(void *__restrict, const void *__restrict, size_t);
+void *memcpy(void *__restrict, const void *__restrict, size_t);
 
-void * memmem(const void *, size_t, const void *, size_t);
+void *memmem(const void *, size_t, const void *, size_t);
 
-void * memmove(void *, const void *, size_t);
+void *memmove(void *, const void *, size_t);
 
-void * mempcpy(void *__restrict, const void *__restrict, size_t);
+void *mempcpy(void *__restrict, const void *__restrict, size_t);
 
-void * memrchr(const void *, int, size_t);
+void *memrchr(const void *, int, size_t);
 
-void * memset(void *, int, size_t);
+void *memset(void *, int, size_t);
 
-void * memset_explicit(void *, int, size_t);
+void *memset_explicit(void *, int, size_t);
 
-char * stpcpy(char *__restrict, const char *__restrict);
+char *stpcpy(char *__restrict, const char *__restrict);
 
-char * stpncpy(char *__restrict, const char *__restrict, size_t);
+char *stpncpy(char *__restrict, const char *__restrict, size_t);
 
-char * strcasestr(const char *, const char *);
+char *strcasestr(const char *, const char *);
 
-char * strcat(char *__restrict, const char *__restrict);
+char *strcat(char *__restrict, const char *__restrict);
 
-char * strchr(const char *, int);
+char *strchr(const char *, int);
 
-char * strchrnul(const char *, int);
+char *strchrnul(const char *, int);
 
 int strcmp(const char *, const char *);
 
 int strcoll(const char *, const char *);
 
-char * strcpy(char *__restrict, const char *__restrict);
+char *strcpy(char *__restrict, const char *__restrict);
 
 size_t strcspn(const char *, const char *);
 
-char * strdup(const char *);
+char *strdup(const char *);
 
-char * strerror(int);
+char *strerror(int);
 
-char * strerror_r(int, char *, size_t);
+char *strerror_r(int, char *, size_t);
 
 size_t strlcat(const char *__restrict, const char *__restrict, size_t);
 
@@ -69,31 +69,31 @@ size_t strlcpy(const char *__restrict, const char *__restrict, size_t);
 
 size_t strlen(const char *);
 
-char * strncat(char *, const char *, size_t);
+char *strncat(char *, const char *, size_t);
 
 int strncmp(const char *, const char *, size_t);
 
-char * strncpy(char *__restrict, const char *__restrict, size_t);
+char *strncpy(char *__restrict, const char *__restrict, size_t);
 
-char * strndup(const char *, size_t);
+char *strndup(const char *, size_t);
 
 size_t strnlen(const char *, size_t);
 
-char * strpbrk(const char *, const char *);
+char *strpbrk(const char *, const char *);
 
-char * strrchr(const char *, int);
+char *strrchr(const char *, int);
 
-char * strsep(char * *__restrict, const char *__restrict);
+char *strsep(char **__restrict, const char *__restrict);
 
-char * strsignal(int);
+char *strsignal(int);
 
 size_t strspn(const char *, const char *);
 
-char * strstr(const char *, const char *);
+char *strstr(const char *, const char *);
 
-char * strtok(char *__restrict, const char *__restrict);
+char *strtok(char *__restrict, const char *__restrict);
 
-char * strtok_r(char *__restrict, const char *__restrict, char * *__restrict);
+char *strtok_r(char *__restrict, const char *__restrict, char **__restrict);
 
 size_t strxfrm(char *__restrict, const char *__restrict, size_t);
 

>From 80650e02396028acc1d844aba4b2da3a75fbc5d3 Mon Sep 17 00:00:00 2001
From: Aaryan Shukla <aaryanshukla at google.com>
Date: Tue, 2 Jul 2024 20:21:54 +0000
Subject: [PATCH 5/6] using small testing files instead

changed header.py for spacing issues
added .strip to script for spacing issues
---
 libc/newhdrgen/header.py                      |  12 +-
 libc/newhdrgen/tests/expected_output/string.h | 102 ------
 .../tests/expected_output/test_header.h       |  36 +++
 .../input/{string.h.def => test_small.h.def}  |  11 +-
 libc/newhdrgen/tests/input/test_small.yaml    |  32 ++
 libc/newhdrgen/tests/input/test_string.yaml   | 303 ------------------
 libc/newhdrgen/tests/test_integration.py      |  35 +-
 libc/newhdrgen/yaml_to_classes.py             |   1 +
 8 files changed, 106 insertions(+), 426 deletions(-)
 delete mode 100644 libc/newhdrgen/tests/expected_output/string.h
 create mode 100644 libc/newhdrgen/tests/expected_output/test_header.h
 rename libc/newhdrgen/tests/input/{string.h.def => test_small.h.def} (60%)
 create mode 100644 libc/newhdrgen/tests/input/test_small.yaml
 delete mode 100644 libc/newhdrgen/tests/input/test_string.yaml

diff --git a/libc/newhdrgen/header.py b/libc/newhdrgen/header.py
index 7ce356831677e..f12afdc4c9728 100644
--- a/libc/newhdrgen/header.py
+++ b/libc/newhdrgen/header.py
@@ -46,9 +46,6 @@ def __str__(self):
         for macro in self.macros:
             content.append(str(macro))
 
-        for object in self.objects:
-            content.append(str(object))
-
         for type_ in self.types:
             content.append(str(type_))
 
@@ -58,10 +55,13 @@ def __str__(self):
                 content.append(f"\t{str(enum)},")
             content.append("};")
 
-        # TODO: replace line below with common.h functionality
-        content.append("__BEGIN_C_DECLS\n")
+        content.append("\n__BEGIN_C_DECLS\n")
+
         for function in self.functions:
             content.append(str(function))
             content.append("")
-        content.append("__END_C_DECLS\n")
+        for object in self.objects:
+            content.append(str(object))
+        content.append("__END_C_DECLS")
+
         return "\n".join(content)
diff --git a/libc/newhdrgen/tests/expected_output/string.h b/libc/newhdrgen/tests/expected_output/string.h
deleted file mode 100644
index 12ec66e4ff55b..0000000000000
--- a/libc/newhdrgen/tests/expected_output/string.h
+++ /dev/null
@@ -1,102 +0,0 @@
-//===-- C standard library header string.h --------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_LIBC_STRING_H
-#define LLVM_LIBC_STRING_H
-
-#include "__llvm-libc-common.h"
-
-#include "llvm-libc-macros/null-macro.h"
-
-#include <llvm-libc-types/size_t.h>
-
-__BEGIN_C_DECLS
-
-void *memccpy(void *__restrict, const void *__restrict, int, size_t);
-
-void *memchr(const void *, int, size_t);
-
-int memcmp(const void *, const void *, size_t);
-
-void *memcpy(void *__restrict, const void *__restrict, size_t);
-
-void *memmem(const void *, size_t, const void *, size_t);
-
-void *memmove(void *, const void *, size_t);
-
-void *mempcpy(void *__restrict, const void *__restrict, size_t);
-
-void *memrchr(const void *, int, size_t);
-
-void *memset(void *, int, size_t);
-
-void *memset_explicit(void *, int, size_t);
-
-char *stpcpy(char *__restrict, const char *__restrict);
-
-char *stpncpy(char *__restrict, const char *__restrict, size_t);
-
-char *strcasestr(const char *, const char *);
-
-char *strcat(char *__restrict, const char *__restrict);
-
-char *strchr(const char *, int);
-
-char *strchrnul(const char *, int);
-
-int strcmp(const char *, const char *);
-
-int strcoll(const char *, const char *);
-
-char *strcpy(char *__restrict, const char *__restrict);
-
-size_t strcspn(const char *, const char *);
-
-char *strdup(const char *);
-
-char *strerror(int);
-
-char *strerror_r(int, char *, size_t);
-
-size_t strlcat(const char *__restrict, const char *__restrict, size_t);
-
-size_t strlcpy(const char *__restrict, const char *__restrict, size_t);
-
-size_t strlen(const char *);
-
-char *strncat(char *, const char *, size_t);
-
-int strncmp(const char *, const char *, size_t);
-
-char *strncpy(char *__restrict, const char *__restrict, size_t);
-
-char *strndup(const char *, size_t);
-
-size_t strnlen(const char *, size_t);
-
-char *strpbrk(const char *, const char *);
-
-char *strrchr(const char *, int);
-
-char *strsep(char **__restrict, const char *__restrict);
-
-char *strsignal(int);
-
-size_t strspn(const char *, const char *);
-
-char *strstr(const char *, const char *);
-
-char *strtok(char *__restrict, const char *__restrict);
-
-char *strtok_r(char *__restrict, const char *__restrict, char **__restrict);
-
-size_t strxfrm(char *__restrict, const char *__restrict, size_t);
-
-__END_C_DECLS
-
-#endif // LLVM_LIBC_STRING_H
diff --git a/libc/newhdrgen/tests/expected_output/test_header.h b/libc/newhdrgen/tests/expected_output/test_header.h
new file mode 100644
index 0000000000000..552f93eadf44d
--- /dev/null
+++ b/libc/newhdrgen/tests/expected_output/test_header.h
@@ -0,0 +1,36 @@
+//===-- C standard library header test_small-------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_TEST_SMALL_H
+#define LLVM_LIBC_TEST_SMALL_H
+
+#include "__llvm-libc-common.h"
+#include "llvm-libc-macros/test_small-macros.h"
+
+#define MACRO_A 1
+#define MACRO_B 2
+
+#include <llvm-libc-types/type_a.h>
+#include <llvm-libc-types/type_b.h>
+
+enum {
+  enum_a = value_1,
+  enum_b = value_2,
+};
+
+__BEGIN_C_DECLS
+
+void func_a();
+
+int func_b(int, float);
+
+extern obj object_1 extern obj object_2
+
+    __END_C_DECLS
+
+#endif // LLVM_LIBC_TEST_SMALL_H
diff --git a/libc/newhdrgen/tests/input/string.h.def b/libc/newhdrgen/tests/input/test_small.h.def
similarity index 60%
rename from libc/newhdrgen/tests/input/string.h.def
rename to libc/newhdrgen/tests/input/test_small.h.def
index 1bd2687db2bea..38f86699840c7 100644
--- a/libc/newhdrgen/tests/input/string.h.def
+++ b/libc/newhdrgen/tests/input/test_small.h.def
@@ -1,4 +1,4 @@
-//===-- C standard library header string.h --------------------------------===//
+ //===-- C standard library header test_small-------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,13 +6,12 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_LIBC_STRING_H
-#define LLVM_LIBC_STRING_H
+#ifndef LLVM_LIBC_TEST_SMALL_H
+#define LLVM_LIBC_TEST_SMALL_H
 
 #include "__llvm-libc-common.h"
-
-#include "llvm-libc-macros/null-macro.h"
+#include "llvm-libc-macros/test_small-macros.h"
 
 %%public_api()
 
-#endif // LLVM_LIBC_STRING_H
+#endif // LLVM_LIBC_TEST_SMALL_H
diff --git a/libc/newhdrgen/tests/input/test_small.yaml b/libc/newhdrgen/tests/input/test_small.yaml
new file mode 100644
index 0000000000000..a3cbd2e21327a
--- /dev/null
+++ b/libc/newhdrgen/tests/input/test_small.yaml
@@ -0,0 +1,32 @@
+header: test_header.h
+macros:
+  - macro_name: MACRO_A
+    macro_value: 1
+  - macro_name: MACRO_B
+    macro_value: 2
+types:
+  - type_name: type_a
+  - type_name: type_b
+enums:
+  - name: enum_a
+    value: value_1
+  - name: enum_b
+    value: value_3
+objects:
+  - object_name: object_1
+    object_type: obj
+  - object_name: object_2
+    object_type: obj
+functions:
+  - name: func_a
+    return_type: void
+    arguments: []
+    standards: 
+      - stdc
+  - name: func_b
+    return_type: int
+    arguments:
+      - type: int
+      - type: float
+    standards: 
+      - stdc
diff --git a/libc/newhdrgen/tests/input/test_string.yaml b/libc/newhdrgen/tests/input/test_string.yaml
deleted file mode 100644
index 2754f856bc807..0000000000000
--- a/libc/newhdrgen/tests/input/test_string.yaml
+++ /dev/null
@@ -1,303 +0,0 @@
-header: string.h
-macros: []
-types:
-  - type_name: size_t
-enums: []
-objects: []
-functions:
-  - name: memcpy
-    standards: 
-      - stdc
-    return_type: void *
-    arguments:
-      - type: void *__restrict
-      - type: const void *__restrict
-      - type: size_t
-  - name: memmove
-    standards: 
-      - stdc
-    return_type: void *
-    arguments:
-      - type: void *
-      - type: const void *
-      - type: size_t
-  - name: memcmp
-    standards: 
-      - stdc
-    return_type: int
-    arguments:
-      - type: const void *
-      - type: const void *
-      - type: size_t
-  - name: memchr
-    standards: 
-      - stdc
-    return_type: void *
-    arguments:
-      - type: const void *
-      - type: int
-      - type: size_t
-  - name: memset
-    standards: 
-      - stdc
-    return_type: void *
-    arguments:
-      - type: void *
-      - type: int
-      - type: size_t
-  - name: memset_explicit
-    standards: 
-      - stdc
-    return_type: void *
-    arguments:
-      - type: void *
-      - type: int
-      - type: size_t
-  - name: strcpy
-    standards: 
-      - stdc
-    return_type: char
-    arguments:
-      - type: char *__restrict
-      - type: const char *__restrict
-  - name: strncpy
-    standards: 
-      - stdc
-    return_type: char *
-    arguments:
-      - type: char *__restrict
-      - type: const char *__restrict
-      - type: size_t
-  - name: strcat
-    standards: 
-      - stdc
-    return_type: char *
-    arguments:
-      - type: char *__restrict
-      - type: const char *__restrict
-  - name: strncat
-    standards: 
-      - stdc
-    return_type: char *
-    arguments:
-      - type: char *
-      - type: const char *
-      - type: size_t
-  - name: strcmp
-    standards: 
-      - stdc
-    return_type: int
-    arguments:
-      - type: const char *
-      - type: const char *
-  - name: strcoll
-    standards: 
-      - stdc
-    return_type: int
-    arguments:
-      - type: const char *
-      - type: const char *
-  - name: strncmp
-    standards: 
-      - stdc
-    return_type: int
-    arguments:
-      - type: const char *
-      - type: const char *
-      - type: size_t
-  - name: strxfrm
-    standards: 
-      - stdc
-    return_type: size_t
-    arguments:
-      - type: char *__restrict
-      - type: const char *__restrict
-      - type: size_t
-  - name: strchr
-    standards: 
-      - stdc
-    return_type: char *
-    arguments:
-      - type: const char *
-      - type: int
-  - name: strcspn
-    standards: 
-      - stdc
-    return_type: size_t
-    arguments:
-      - type: const char *
-      - type: const char *
-  - name: strdup
-    return_type: char *
-    arguments:
-      - type: const char *
-  - name: strndup
-    standards: 
-      - stdc
-    return_type: char *
-    arguments:
-      - type: const char *
-      - type: size_t
-  - name: strpbrk
-    standards: 
-      - stdc
-    return_type: char *
-    arguments:
-      - type: const char *
-      - type: const char *
-  - name: strrchr
-    standards: 
-      - stdc
-    return_type: char *
-    arguments:
-      - type: const char *
-      - type: int
-  - name: strspn
-    standards: 
-      - stdc
-    return_type: size_t
-    arguments:
-      - type: const char *
-      - type: const char *
-  - name: strstr
-    standards: 
-      - stdc
-    return_type: char *
-    arguments:
-      - type: const char *
-      - type: const char *
-  - name: strtok
-    standards: 
-      - stdc
-    return_type: char *
-    arguments:
-      - type: char *__restrict
-      - type: const char *__restrict
-  - name: strerror
-    standards: 
-      - stdc
-    return_type: char *
-    arguments:
-      - type: int
-  - name: strlen
-    standards: 
-      - stdc
-    return_type: size_t
-    arguments:
-      - type: const char *
-  - name: memccpy
-    standards: 
-      - POSIX
-    return_type: void *
-    arguments:
-      - type: void *__restrict
-      - type: const void *__restrict
-      - type: int
-      - type: size_t
-  - name: mempcpy
-    standards: 
-      - POSIX
-    return_type: void *
-    arguments:
-      - type: void *__restrict
-      - type: const void *__restrict
-      - type: size_t
-  - name: stpcpy
-    standards: 
-      - POSIX
-    return_type: char *
-    arguments:
-      - type: char *__restrict
-      - type: const char *__restrict
-  - name: stpncpy
-    standards: 
-      - POSIX
-    return_type: char *
-    arguments:
-      - type: char *__restrict
-      - type: const char *__restrict
-      - type: size_t
-  - name: strnlen
-    standards: 
-      - POSIX
-    return_type: size_t
-    arguments:
-      - type: const char *
-      - type: size_t
-  - name: strtok_r
-    standards: 
-      - POSIX
-    return_type: char *
-    arguments:
-      - type: char *__restrict
-      - type: const char *__restrict
-      - type: char ** __restrict
-  - name: strsignal
-    standards: 
-      - POSIX
-    return_type: char *
-    arguments:
-      - type: int
-  - name: memmem
-    standards: 
-      - GNUExtensions
-    return_type: void *
-    arguments:
-      - type: const void *
-      - type: size_t
-      - type: const void *
-      - type: size_t
-  - name: memrchr
-    standards: 
-      - GNUExtensions
-    return_type: void *
-    arguments:
-      - type: const void *
-      - type: int
-      - type: size_t
-  - name: strerror_r
-    standards: 
-      - GNUExtensions
-    return_type: char *
-    arguments:
-      - type: int
-      - type: char *
-      - type: size_t
-  - name: strcasestr
-    standards: 
-      - GNUExtensions
-    return_type: char *
-    arguments:
-      - type: const char *
-      - type: const char *
-  - name: strchrnul
-    standards: 
-      - GNUExtensions
-    return_type: char *
-    arguments:
-      - type: const char *
-      - type: int
-  - name: strlcat
-    standards: 
-      - BSDExtensions
-    return_type: size_t
-    arguments:
-      - type: char *__restrict
-      - type: char *__restrict
-      - type: size_t
-  - name: strlcpy
-    standards: 
-      - BSDExtensions
-    return_type: size_t
-    arguments:
-      - type: char *__restrict
-      - type: char *__restrict
-      - type: size_t
-  - name: strsep
-    standards: 
-      - BSDExtensions
-    return_type: char *
-    arguments:
-      - type: char **__restrict
-      - type: char *__restrict
-
diff --git a/libc/newhdrgen/tests/test_integration.py b/libc/newhdrgen/tests/test_integration.py
index 1a942b461ad02..1aa7e550520aa 100644
--- a/libc/newhdrgen/tests/test_integration.py
+++ b/libc/newhdrgen/tests/test_integration.py
@@ -1,20 +1,36 @@
 import subprocess
 import unittest
 from pathlib import Path
+import os
+import argparse
 
 
 class TestHeaderGenIntegration(unittest.TestCase):
     def setUp(self):
-        self.output_dir = Path("tests/output")
+        parser = argparse.ArgumentParser(
+            description="TestHeaderGenIntegration arguments"
+        )
+        parser.add_argument(
+            "--output_dir", type=str, help="Output directory for generated headers"
+        )
+        args, _ = parser.parse_known_args()
+        output_dir_env = os.getenv("TEST_OUTPUT_DIR")
+
+        self.output_dir = Path(
+            args.output_dir
+            if args.output_dir
+            else output_dir_env if output_dir_env else "libc/newhdrgen/tests/output"
+        )
+
         self.maxDiff = None
 
     def run_script(self, yaml_file, h_def_file, output_dir):
         result = subprocess.run(
             [
                 "python3",
-                "yaml_to_classes.py",
-                yaml_file,
-                h_def_file,
+                "libc/newhdrgen/yaml_to_classes.py",
+                str(yaml_file),
+                str(h_def_file),
                 "--output_dir",
                 str(output_dir),
             ],
@@ -35,11 +51,12 @@ def compare_files(self, generated_file, expected_file):
         self.assertEqual(gen_content, exp_content)
 
     def test_generate_header(self):
-        # this is for example, will find a way to test everything at once
-        yaml_file = Path("tests/input/test_string.yaml")
-        h_def_file = Path("tests/input/string.h.def")
-        expected_output_file = Path("tests/expected_output/string.h")
-        output_file = self.output_dir / "string.h"
+        yaml_file = Path("libc/newhdrgen/tests/input/test_small.yaml")
+        h_def_file = Path("libc/newhdrgen/tests/input/test_small.h.def")
+        expected_output_file = Path(
+            "libc/newhdrgen/tests/expected_output/test_header.h"
+        )
+        output_file = self.output_dir / "test_small.h"
 
         if not self.output_dir.exists():
             self.output_dir.mkdir(parents=True)
diff --git a/libc/newhdrgen/yaml_to_classes.py b/libc/newhdrgen/yaml_to_classes.py
index e489c7f509b8e..9e0337f4a308e 100644
--- a/libc/newhdrgen/yaml_to_classes.py
+++ b/libc/newhdrgen/yaml_to_classes.py
@@ -101,6 +101,7 @@ def fill_public_api(header_str, h_def_content):
     Returns:
         The final header content with the public API filled in.
     """
+    header_str = header_str.strip()
     return h_def_content.replace("%%public_api()", header_str, 1)
 
 

>From e104bc35f1f423d64cce52d0eba3664a4c234191 Mon Sep 17 00:00:00 2001
From: Aaryan Shukla <aaryanshukla at google.com>
Date: Tue, 2 Jul 2024 20:51:53 +0000
Subject: [PATCH 6/6] fixed formatting

---
 libc/newhdrgen/tests/test_integration.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/libc/newhdrgen/tests/test_integration.py b/libc/newhdrgen/tests/test_integration.py
index 1aa7e550520aa..88db65f5d4f61 100644
--- a/libc/newhdrgen/tests/test_integration.py
+++ b/libc/newhdrgen/tests/test_integration.py
@@ -19,7 +19,9 @@ def setUp(self):
         self.output_dir = Path(
             args.output_dir
             if args.output_dir
-            else output_dir_env if output_dir_env else "libc/newhdrgen/tests/output"
+            else output_dir_env 
+            if output_dir_env 
+            else "libc/newhdrgen/tests/output"
         )
 
         self.maxDiff = None



More information about the libc-commits mailing list