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

via libc-commits libc-commits at lists.llvm.org
Wed Jul 3 14:29:56 PDT 2024


Author: aaryanshukla
Date: 2024-07-03T14:29:51-07:00
New Revision: 6aed0d5afb53434068f37f1b2909590e9dda3d8f

URL: https://github.com/llvm/llvm-project/commit/6aed0d5afb53434068f37f1b2909590e9dda3d8f
DIFF: https://github.com/llvm/llvm-project/commit/6aed0d5afb53434068f37f1b2909590e9dda3d8f.diff

LOG: [libc] created integration tests for newhdrgen (#97361)

- created integration tests for libc hdrgen 
- implemented sorting function names in yaml files through script

Added: 
    libc/newhdrgen/CMakeLists.txt
    libc/newhdrgen/tests/expected_output/test_header.h
    libc/newhdrgen/tests/input/test_small.h.def
    libc/newhdrgen/tests/input/test_small.yaml
    libc/newhdrgen/tests/output/test_small.h
    libc/newhdrgen/tests/test_integration.py

Modified: 
    libc/CMakeLists.txt
    libc/newhdrgen/class_implementation/classes/enumeration.py
    libc/newhdrgen/class_implementation/classes/function.py
    libc/newhdrgen/class_implementation/classes/object.py
    libc/newhdrgen/header.py
    libc/newhdrgen/yaml_to_classes.py

Removed: 
    


################################################################################
diff  --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt
index 013b17b03f570..6ba54475d0fd1 100644
--- a/libc/CMakeLists.txt
+++ b/libc/CMakeLists.txt
@@ -50,6 +50,10 @@ set(LIBC_NAMESPACE ${default_namespace}
   CACHE STRING "The namespace to use to enclose internal implementations. Must start with '__llvm_libc'."
 )
 
+
+add_subdirectory(newhdrgen)
+
+
 if(LLVM_LIBC_FULL_BUILD OR LLVM_LIBC_GPU_BUILD)
   if(NOT LIBC_HDRGEN_EXE)
     # We need to set up hdrgen first since other targets depend on it.

diff  --git a/libc/newhdrgen/CMakeLists.txt b/libc/newhdrgen/CMakeLists.txt
new file mode 100644
index 0000000000000..33750d181c4b3
--- /dev/null
+++ b/libc/newhdrgen/CMakeLists.txt
@@ -0,0 +1,17 @@
+if(LLVM_LIBC_FULL_BUILD)
+
+  enable_testing()
+
+  set(NEWHDGEN_TESTS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/tests)
+
+  add_test(
+    NAME newhdrgen_integration_test
+    COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${CMAKE_CURRENT_SOURCE_DIR} python3 ${NEWHDGEN_TESTS_DIR}/test_integration.py
+  )
+  
+  add_custom_target(check-newhdrgen
+    COMMAND ${CMAKE_CTEST_COMMAND} -R newhdrgen_integration_test
+  )
+
+  message(STATUS "Integration test for newhdrgen added.")
+endif()

diff  --git a/libc/newhdrgen/class_implementation/classes/enumeration.py b/libc/newhdrgen/class_implementation/classes/enumeration.py
index be03dbf603c2b..a01fa74210101 100644
--- a/libc/newhdrgen/class_implementation/classes/enumeration.py
+++ b/libc/newhdrgen/class_implementation/classes/enumeration.py
@@ -10,7 +10,7 @@
 
 
 class Enumeration:
-    def __init__(self, name, value=None):
+    def __init__(self, name, value):
         self.name = name
         self.value = value
 

diff  --git a/libc/newhdrgen/class_implementation/classes/function.py b/libc/newhdrgen/class_implementation/classes/function.py
index 3c464e48b6e3b..f79b53de9ade4 100644
--- a/libc/newhdrgen/class_implementation/classes/function.py
+++ b/libc/newhdrgen/class_implementation/classes/function.py
@@ -11,19 +11,19 @@
 
 class Function:
     def __init__(
-        self, standards, return_type, name, arguments, guard=None, attributes=[]
+        self, return_type, name, arguments, standards, guard=None, attributes=[]
     ):
-        self.standards = standards
         self.return_type = return_type
         self.name = name
         self.arguments = [
             arg if isinstance(arg, str) else arg["type"] for arg in arguments
         ]
+        self.standards = standards
         self.guard = guard
         self.attributes = attributes or []
 
     def __str__(self):
-        attributes_str = " ".join(self.attributes)
+        attributes_str = self.attributes
         arguments_str = ", ".join(self.arguments)
         result = f"{self.return_type} {self.name}({arguments_str}){attributes_str};"
         if self.guard:

diff  --git a/libc/newhdrgen/class_implementation/classes/object.py b/libc/newhdrgen/class_implementation/classes/object.py
index c65a82e1a660d..02f30cba1c48c 100644
--- a/libc/newhdrgen/class_implementation/classes/object.py
+++ b/libc/newhdrgen/class_implementation/classes/object.py
@@ -15,4 +15,4 @@ def __init__(self, name, type):
         self.type = type
 
     def __str__(self):
-        return f"extern {self.type} {self.name}"
+        return f"extern {self.type} {self.name};"

diff  --git a/libc/newhdrgen/header.py b/libc/newhdrgen/header.py
index 7ce356831677e..4eaf7dccca9e8 100644
--- a/libc/newhdrgen/header.py
+++ b/libc/newhdrgen/header.py
@@ -44,24 +44,24 @@ def __str__(self):
             content.append(str(include))
 
         for macro in self.macros:
-            content.append(str(macro))
-
-        for object in self.objects:
-            content.append(str(object))
+            content.append(f"{macro}\n")
 
         for type_ in self.types:
-            content.append(str(type_))
+            content.append(f"{type_}")
 
         if self.enumerations:
-            content.append("enum {")
-            for enum in self.enumerations:
-                content.append(f"\t{str(enum)},")
-            content.append("};")
+            combined_enum_content = ",\n  ".join(
+                str(enum) for enum in self.enumerations
+            )
+            content.append(f"\nenum {{\n  {combined_enum_content},\n}};")
+
+        content.append("\n__BEGIN_C_DECLS\n")
 
-        # TODO: replace line below with common.h functionality
-        content.append("__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("\n__END_C_DECLS")
+
         return "\n".join(content)

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..d6ae0d0e282e7
--- /dev/null
+++ b/libc/newhdrgen/tests/expected_output/test_header.h
@@ -0,0 +1,42 @@
+//===-- 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
+
+#ifdef FUNC_A_16
+void func_a()CONST_FUNC_A;
+#endif // FUNC_A_16
+
+#ifdef FUNC_B_16
+int func_b(int, float)CONST_FUNC_B;
+#endif // FUNC_B_16
+
+extern obj object_1;
+extern obj object_2;
+
+__END_C_DECLS
+
+#endif // LLVM_LIBC_TEST_SMALL_H

diff  --git a/libc/newhdrgen/tests/input/test_small.h.def b/libc/newhdrgen/tests/input/test_small.h.def
new file mode 100644
index 0000000000000..de39a8b7e254d
--- /dev/null
+++ b/libc/newhdrgen/tests/input/test_small.h.def
@@ -0,0 +1,17 @@
+//===-- 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"
+
+%%public_api()
+
+#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..0bc292db72396
--- /dev/null
+++ b/libc/newhdrgen/tests/input/test_small.yaml
@@ -0,0 +1,36 @@
+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_2
+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
+    guard: FUNC_A_16
+    attributes: CONST_FUNC_A
+  - name: func_b
+    return_type: int
+    arguments:
+      - type: int
+      - type: float
+    standards: 
+      - stdc
+    guard: FUNC_B_16
+    attributes: CONST_FUNC_B

diff  --git a/libc/newhdrgen/tests/output/test_small.h b/libc/newhdrgen/tests/output/test_small.h
new file mode 100644
index 0000000000000..d6ae0d0e282e7
--- /dev/null
+++ b/libc/newhdrgen/tests/output/test_small.h
@@ -0,0 +1,42 @@
+//===-- 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
+
+#ifdef FUNC_A_16
+void func_a()CONST_FUNC_A;
+#endif // FUNC_A_16
+
+#ifdef FUNC_B_16
+int func_b(int, float)CONST_FUNC_B;
+#endif // FUNC_B_16
+
+extern obj object_1;
+extern obj object_2;
+
+__END_C_DECLS
+
+#endif // LLVM_LIBC_TEST_SMALL_H

diff  --git a/libc/newhdrgen/tests/test_integration.py b/libc/newhdrgen/tests/test_integration.py
new file mode 100644
index 0000000000000..228fecc7f41c0
--- /dev/null
+++ b/libc/newhdrgen/tests/test_integration.py
@@ -0,0 +1,74 @@
+import subprocess
+import unittest
+from pathlib import Path
+import os
+import argparse
+
+
+class TestHeaderGenIntegration(unittest.TestCase):
+    def setUp(self):
+        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
+        # Adjust based on your directory structure such as being in build etc.
+        self.source_dir = Path(__file__).resolve().parent.parent.parent.parent
+
+    def run_script(self, yaml_file, h_def_file, output_dir):
+        yaml_file = self.source_dir / yaml_file
+        h_def_file = self.source_dir / h_def_file
+        result = subprocess.run(
+            [
+                "python3",
+                str(self.source_dir / "libc/newhdrgen/yaml_to_classes.py"),
+                str(yaml_file),
+                str(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):
+        yaml_file = "libc/newhdrgen/tests/input/test_small.yaml"
+        h_def_file = "libc/newhdrgen/tests/input/test_small.h.def"
+        expected_output_file = (
+            self.source_dir / "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)
+
+        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..9e0337f4a308e 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"],
@@ -99,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)
 
 


        


More information about the libc-commits mailing list