aboutsummaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
authoraaryanshukla <53713108+aaryanshukla@users.noreply.github.com>2024-07-03 14:29:51 -0700
committerGitHub <noreply@github.com>2024-07-03 14:29:51 -0700
commit6aed0d5afb53434068f37f1b2909590e9dda3d8f (patch)
treea785ffc65a2e91d977f0f70f8442f93d09a89a97 /libc
parent4c63672ca706c708de1e49bb29d026a705daa0d2 (diff)
downloadllvm-6aed0d5afb53434068f37f1b2909590e9dda3d8f.zip
llvm-6aed0d5afb53434068f37f1b2909590e9dda3d8f.tar.gz
llvm-6aed0d5afb53434068f37f1b2909590e9dda3d8f.tar.bz2
[libc] created integration tests for newhdrgen (#97361)
- created integration tests for libc hdrgen - implemented sorting function names in yaml files through script
Diffstat (limited to 'libc')
-rw-r--r--libc/CMakeLists.txt4
-rw-r--r--libc/newhdrgen/CMakeLists.txt17
-rw-r--r--libc/newhdrgen/class_implementation/classes/enumeration.py2
-rw-r--r--libc/newhdrgen/class_implementation/classes/function.py6
-rw-r--r--libc/newhdrgen/class_implementation/classes/object.py2
-rw-r--r--libc/newhdrgen/header.py24
-rw-r--r--libc/newhdrgen/tests/expected_output/test_header.h42
-rw-r--r--libc/newhdrgen/tests/input/test_small.h.def17
-rw-r--r--libc/newhdrgen/tests/input/test_small.yaml36
-rw-r--r--libc/newhdrgen/tests/output/test_small.h42
-rw-r--r--libc/newhdrgen/tests/test_integration.py74
-rw-r--r--libc/newhdrgen/yaml_to_classes.py7
12 files changed, 254 insertions, 19 deletions
diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt
index 013b17b..6ba5447 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 0000000..33750d1
--- /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 be03dbf..a01fa74 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 3c464e4..f79b53d 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 c65a82e..02f30cb 100644
--- a/libc/newhdrgen/class_implementation/classes/object.py
+++ b/libc/newhdrgen/class_implementation/classes/object.py
@@ -15,4 +15,4 @@ class Object:
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 7ce3568..4eaf7dc 100644
--- a/libc/newhdrgen/header.py
+++ b/libc/newhdrgen/header.py
@@ -44,24 +44,24 @@ class HeaderFile:
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 0000000..d6ae0d0
--- /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 0000000..de39a8b
--- /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 0000000..0bc292d
--- /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 0000000..d6ae0d0
--- /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 0000000..228fecc
--- /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 9b52c9c..9e0337f 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)