blob: 6381ac877b243a3ebd2baf0dea60d000d37a7d8f [file] [edit]
#!/usr/bin/env python3
"""
Unit tests for LLVM and Subproject CMake Formatter Utility (`libc/utils/cmake_format.py`).
Verifies all 9 formatting rules, dynamic schema learning, codebase idempotency,
and golden output snapshots.
"""
import unittest
import os
import sys
# Add the directory containing cmake_format.py to sys.path
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, SCRIPT_DIR)
import cmake_format
class TestRule1_CommandCasing(unittest.TestCase):
"""Rule 1: Command Casing."""
def test_1_1_builtin_lowercase(self):
"""Rule 1.1: Built-in language commands are cased in lowercase."""
code = "SET(FOO bar)\nIF(FOO)\n ADD_LIBRARY(lib STATIC)\nENDIF()\n"
expected = "set(FOO bar)\nif(FOO)\n add_library(lib STATIC)\nendif()\n"
self.assertEqual(cmake_format.format_cmake_content(code), expected)
def test_1_2_module_canonical_casing(self):
"""Rule 1.2: Module commands retain canonical declared casing."""
code = "externalproject_add(\n proj\n PREFIX\n dir\n)\n"
expected = "ExternalProject_Add(\n proj\n PREFIX\n dir\n)\n"
self.assertEqual(cmake_format.format_cmake_content(code), expected)
def test_1_3_custom_function_casing(self):
"""Rule 1.3: Custom user functions/macros retain their original casing."""
code = "add_libc_unittest(\n my_test\n SRCS\n my_test.cpp\n)\n"
expected = "add_libc_unittest(\n my_test\n SRCS\n my_test.cpp\n)\n"
self.assertEqual(cmake_format.format_cmake_content(code), expected)
class TestRule2_ParenthesisSpacingAndWhitespace(unittest.TestCase):
"""Rule 2: Parenthesis Spacing & Whitespace Collapsing."""
def test_2_1_zero_space_before_opening_paren(self):
"""Rule 2.1: Zero space between command identifier and opening '('."""
code = "set (FOO bar)\n"
expected = "set(FOO bar)\n"
self.assertEqual(cmake_format.format_cmake_content(code), expected)
def test_2_2_collapse_arg_whitespace(self):
"""Rule 2.2: Collapses multiple spaces between single-line arguments down to one."""
code = "add_entrypoint_object(target_name DEPENDS dep1 dep2)\n"
expected = "add_entrypoint_object(target_name DEPENDS dep1 dep2)\n"
self.assertEqual(cmake_format.format_cmake_content(code), expected)
class TestRule3_QuotedAndBracketImmutability(unittest.TestCase):
"""Rule 3: Quoted String & Bracket Immutability."""
def test_3_1_quoted_and_bracket_tokens(self):
"""Rule 3.1: Quoted arguments and bracket arguments are single immutable tokens."""
code = 'set(MSG "Hello \\"World\\"")\nset(CODE [=[raw string\n content]=])\n'
expected = (
'set(MSG "Hello \\"World\\"")\nset(CODE [=[raw string\n content]=])\n'
)
self.assertEqual(cmake_format.format_cmake_content(code), expected)
def test_3_2_multiline_string_preservation(self):
"""Rule 3.2: Multi-line quoted strings are preserved 100% untouched."""
code = 'set(DOC "\n Line 1\n Line 2\n")\n'
expected = 'set(DOC "\n Line 1\n Line 2\n")\n'
self.assertEqual(cmake_format.format_cmake_content(code), expected)
class TestRule4_EmptyClosures(unittest.TestCase):
"""Rule 4: Empty Closures."""
def test_4_1_empty_closing_parens(self):
"""Rule 4.1: Control block closures strip old condition arguments down to empty ()."""
code = "if(FOO)\n set(BAR 1)\nelse(FOO)\n set(BAR 0)\nendif(FOO)\n"
expected = "if(FOO)\n set(BAR 1)\nelse()\n set(BAR 0)\nendif()\n"
self.assertEqual(cmake_format.format_cmake_content(code), expected)
class TestRule5_SchemaAwareKeywordCasing(unittest.TestCase):
"""Rule 5: Schema-Aware Keyword Casing."""
def test_5_1_keyword_uppercasing(self):
"""Rule 5.1: Schema keywords are upper-cased."""
code = "add_entrypoint_object(\n target\n srcs\n src.cpp\n depends\n dep\n)\n"
expected = "add_entrypoint_object(\n target\n SRCS\n src.cpp\n DEPENDS\n dep\n)\n"
self.assertEqual(cmake_format.format_cmake_content(code), expected)
def test_5_2_positional_args_untouched(self):
"""Rule 5.2: Positional arguments, file paths, and target names are left untouched."""
code = "add_header_macro(\n string\n ../libc/include/string.yaml\n string.h\n DEPENDS\n .llvm_libc_common_h\n)\n"
expected = "add_header_macro(\n string\n ../libc/include/string.yaml\n string.h\n DEPENDS\n .llvm_libc_common_h\n)\n"
self.assertEqual(cmake_format.format_cmake_content(code), expected)
def test_5_3_custom_function_positional_args_untouched(self):
"""Rule 5.3: Positional output_var parameters in custom functions retain casing."""
code = '_get_common_compile_options(compile_options "${ADD_OBJECT_FLAGS}")\n'
expected = (
'_get_common_compile_options(compile_options "${ADD_OBJECT_FLAGS}")\n'
)
self.assertEqual(cmake_format.format_cmake_content(code), expected)
class TestRule6_MultilineArgumentLayout(unittest.TestCase):
"""Rule 6: Multi-line Argument Layout & Keyword Schema Mechanics."""
def test_6_1_option_keyword_scope(self):
"""Rule 6.1: Option keywords (0 values) close immediately."""
code = "add_library(\n target\n ALIAS\n real_target\n)\n"
expected = "add_library(\n target\n ALIAS\n real_target\n)\n"
self.assertEqual(cmake_format.format_cmake_content(code), expected)
def test_6_2_single_value_keyword_scope(self):
"""Rule 6.2: Single-value keywords consume 1 argument then close."""
code = "execute_process(\n WORKING_DIRECTORY\n /tmp\n OUTPUT_VARIABLE\n out\n)\n"
expected = "execute_process(\n WORKING_DIRECTORY\n /tmp\n OUTPUT_VARIABLE\n out\n)\n"
self.assertEqual(cmake_format.format_cmake_content(code), expected)
def test_6_3a_multivalue_separate_line(self):
"""Rule 6.3a: Multi-value keyword on new line indents items +4 spaces (+2 relative to keyword)."""
code = "add_entrypoint_object(\n target\n SRCS\n s1.cpp\n s2.cpp\n)\n"
expected = (
"add_entrypoint_object(\n target\n SRCS\n s1.cpp\n s2.cpp\n)\n"
)
self.assertEqual(cmake_format.format_cmake_content(code), expected)
def test_6_3b_multivalue_header_line(self):
"""Rule 6.3b: Multi-value keyword on header line indents items +2 spaces relative to call base."""
code = "add_entrypoint_object(target SRCS s1.cpp s2.cpp)\n"
expected = "add_entrypoint_object(target SRCS s1.cpp s2.cpp)\n"
self.assertEqual(cmake_format.format_cmake_content(code), expected)
def test_6_4_argument_forwarding_vars(self):
"""Rule 6.4: Argument forwarding variables (${ARGN}, ${ARGV}) align at +2 spaces and reset active keyword."""
code = "add_entrypoint_object(\n target\n DEPENDS\n dep1\n ${ARGN}\n)\n"
expected = (
"add_entrypoint_object(\n target\n DEPENDS\n dep1\n ${ARGN}\n)\n"
)
self.assertEqual(cmake_format.format_cmake_content(code), expected)
def test_6_5_closing_paren_indent(self):
"""Rule 6.5: Closing parenthesis ')' aligns at +0 spaces (call base)."""
code = "add_entrypoint_object(\n target\n SRCS\n s1.cpp\n)\n"
expected = "add_entrypoint_object(\n target\n SRCS\n s1.cpp\n)\n"
self.assertEqual(cmake_format.format_cmake_content(code), expected)
class TestRule7_ControlBlockIndentation(unittest.TestCase):
"""Rule 7: Control Block Indentation."""
def test_7_1_nested_control_blocks(self):
"""Rule 7.1: Nests 2 spaces per control block level."""
code = "if(A)\nif(B)\nset(C 1)\nendif()\nendif()\n"
expected = "if(A)\n if(B)\n set(C 1)\n endif()\nendif()\n"
self.assertEqual(cmake_format.format_cmake_content(code), expected)
def test_7_2_middle_blocks(self):
"""Rule 7.2: else() and elseif() align at block base level."""
code = "if(A)\nset(X 1)\nelseif(B)\nset(X 2)\nelse()\nset(X 3)\nendif()\n"
expected = (
"if(A)\n set(X 1)\nelseif(B)\n set(X 2)\nelse()\n set(X 3)\nendif()\n"
)
self.assertEqual(cmake_format.format_cmake_content(code), expected)
class TestRule8_CommentFormatting(unittest.TestCase):
"""Rule 8: Comment Formatting & Lookahead Buffering."""
def test_8_1_lookahead_comment_buffering(self):
"""Rule 8.1: Line comment aligns with the indentation of the upcoming code line."""
code = "add_entrypoint_object(\n target\n SRCS\n # Comment for s1\n s1.cpp\n)\n"
expected = "add_entrypoint_object(\n target\n SRCS\n # Comment for s1\n s1.cpp\n)\n"
self.assertEqual(cmake_format.format_cmake_content(code), expected)
def test_8_2_standalone_comments_blank_line(self):
"""Rule 8.2: Standalone comments followed by a blank line flush at current base indent."""
code = "# Standalone comment\n\nadd_library(target s1.cpp)\n"
expected = "# Standalone comment\n\nadd_library(target s1.cpp)\n"
self.assertEqual(cmake_format.format_cmake_content(code), expected)
def test_8_3a_closing_paren_keyword_comment(self):
"""Rule 8.3a: Comment following a keyword before closing ')' indents under keyword (+4 spaces).
In practice, UNIT_TEST_ONLY is learned as an option from cmake_parse_arguments in
LLVMLibCTestRules.cmake via pre_scan_workspace_modules. We supply an equivalent
inline definition so the test is self-contained.
"""
# Inline definition matching the real LLVMLibCTestRules.cmake declaration.
schema_stub = """
function(add_libc_test test_name)
cmake_parse_arguments(
"LIBC_TEST"
"UNIT_TEST_ONLY;HERMETIC_TEST_ONLY"
""
""
${ARGN}
)
endfunction()
"""
ctx = cmake_format.FormatterContext()
cmake_format.scan_dynamic_schemas(schema_stub, ctx=ctx)
code = "add_libc_test(\n hash_test\n UNIT_TEST_ONLY\n # Explanation for option\n)\n"
expected = "add_libc_test(\n hash_test\n UNIT_TEST_ONLY\n # Explanation for option\n)\n"
self.assertEqual(cmake_format.format_cmake_content(code, ctx=ctx), expected)
def test_8_3b_closing_paren_list_comment(self):
"""Rule 8.3b: Comment following a list item before closing ')' aligns at top-level call (+2 spaces)."""
code = "add_libc_test(\n stdbit_test\n DEPENDS\n dep1\n # Top level call comment\n)\n"
expected = "add_libc_test(\n stdbit_test\n DEPENDS\n dep1\n # Top level call comment\n)\n"
self.assertEqual(cmake_format.format_cmake_content(code), expected)
def test_8_4_comment_space_hygiene(self):
"""Rule 8.4: Missing space after '#' is added; special markers (#---, #!) preserved."""
code = "#no space\n#--- header ---\n#!shebang\n"
expected = "# no space\n#--- header ---\n#!shebang\n"
self.assertEqual(cmake_format.format_cmake_content(code), expected)
class TestRule9_CleanlinessAndFileHygiene(unittest.TestCase):
"""Rule 9: Cleanliness & File Hygiene."""
def test_9_1_strip_trailing_whitespace(self):
"""Rule 9.1: Trailing whitespace on all lines is stripped."""
code = "set(FOO bar) \nset(BAR baz) \n"
expected = "set(FOO bar)\nset(BAR baz)\n"
self.assertEqual(cmake_format.format_cmake_content(code), expected)
def test_9_2_single_trailing_newline(self):
"""Rule 9.2: Non-empty files end with exactly one trailing newline."""
code = "set(FOO bar)\n\n\n"
expected = "set(FOO bar)\n"
self.assertEqual(cmake_format.format_cmake_content(code), expected)
def test_9_3_empty_file_preservation(self):
"""Rule 9.3: Empty 0-byte files are preserved as 0-byte."""
self.assertEqual(cmake_format.format_cmake_content(""), "")
self.assertEqual(cmake_format.format_cmake_content(" \n\n \t "), "")
class TestDynamicSchemaLearning(unittest.TestCase):
"""Dynamic Schema Learning Tests."""
def test_function_block_parser(self):
"""Verifies cmake_parse_arguments extraction inside function/macro AST blocks."""
code = """
function(custom_target_func target)
cmake_parse_arguments(
"FUNC"
"OPTION1;OPTION2"
"SINGLE1"
"MULTI1;MULTI2"
${ARGN}
)
endfunction()
"""
cmake_format.scan_dynamic_schemas(code)
schema = cmake_format.get_schema_for_cmd("custom_target_func")
self.assertIn("OPTION1", schema.options)
self.assertIn("SINGLE1", schema.one_value)
self.assertIn("MULTI1", schema.multi_value)
def test_variable_list_scanner(self):
"""Verifies dynamic learning from set(*_OPTION_ARGS), set(*_SINGLE_VALUE_ARGS), set(*_MULTI_VALUE_ARGS)."""
code = """
set(CUSTOM_OPTION_ARGS OPT_A OPT_B)
set(CUSTOM_SINGLE_VALUE_ARGS SING_A)
set(CUSTOM_MULTI_VALUE_ARGS MULT_A MULT_B)
"""
ctx = cmake_format.FormatterContext()
cmake_format.scan_dynamic_schemas(code, ctx=ctx)
self.assertIn("OPT_A", ctx.learned_options)
self.assertIn("SING_A", ctx.learned_one_value)
self.assertIn("MULT_A", ctx.learned_multi_value)
def test_cache_variable_exclusion(self):
"""Verifies cache variable declarations like set(FOO "" CACHE STRING "...") are excluded."""
code = 'set(LIBC_COMPILE_OPTIONS_DEFAULT "" CACHE STRING "Docstring")\n'
ctx = cmake_format.FormatterContext()
cmake_format.scan_dynamic_schemas(code, ctx=ctx)
self.assertNotIn("STRING", ctx.learned_options)
class TestCodebaseIdempotency(unittest.TestCase):
"""Codebase Idempotency Test."""
def test_libc_codebase_idempotency(self):
"""Verifies format(format(content)) == format(content) over libc/ files."""
libc_dir = os.path.join(SCRIPT_DIR, "..")
cmake_files = cmake_format.find_cmake_files([libc_dir])
self.assertGreater(len(cmake_files), 0, "No CMake files found under libc/")
cmake_format.pre_scan_workspace_modules([libc_dir])
for fpath in cmake_files:
with self.subTest(file=fpath):
with open(fpath, "r", encoding="utf-8") as f:
original = f.read()
formatted = cmake_format.format_cmake_content(original)
reformatted = cmake_format.format_cmake_content(formatted)
self.assertEqual(
formatted, reformatted, f"Formatting is not idempotent for {fpath}"
)
class TestEdgeCasesAndIsolation(unittest.TestCase):
"""Edge cases for parenthesis counting in comments/strings and state isolation."""
def test_parens_in_comments_and_strings(self):
"""Verifies parentheses inside comments and strings do not corrupt paren_balance or indentation."""
code = (
"add_custom_target(\n"
" mytarget\n"
" # Comment with parentheses () and (extra)\n"
' "file_with_(parens).cpp"\n'
" DEPENDS\n"
" dep1\n"
")\n"
)
expected = (
"add_custom_target(\n"
" mytarget\n"
" # Comment with parentheses () and (extra)\n"
' "file_with_(parens).cpp"\n'
" DEPENDS\n"
" dep1\n"
")\n"
)
self.assertEqual(cmake_format.format_cmake_content(code), expected)
def test_bracket_comment_with_equals(self):
"""Verifies bracket comments with '=' delimiters (#[=[...]=]) are properly preserved."""
code = (
"#[=[\n"
" Multi-line comment with equals\n"
" set(FOO bar)\n"
"]=]\n"
"set(BAR baz)\n"
)
expected = (
"#[=[\n"
" Multi-line comment with equals\n"
" set(FOO bar)\n"
"]=]\n"
"set(BAR baz)\n"
)
self.assertEqual(cmake_format.format_cmake_content(code), expected)
def test_unterminated_quoted_argument_raises_lexerror(self):
"""Verifies unterminated quoted string arguments raise LexError."""
code_quote = 'set(FOO "unterminated string'
with self.assertRaises(cmake_format.LexError) as cm:
cmake_format.format_cmake_content(code_quote)
self.assertIn("unterminated quoted argument", str(cm.exception))
def test_unterminated_bracket_comment_raises_lexerror(self):
"""Verifies unterminated bracket comments raise LexError."""
code_bc = "#[=[ unterminated bracket comment"
with self.assertRaises(cmake_format.LexError) as cm:
cmake_format.format_cmake_content(code_bc)
self.assertIn("unterminated bracket comment", str(cm.exception))
def test_unterminated_bracket_argument_raises_lexerror(self):
"""Verifies unterminated bracket arguments raise LexError."""
code_ba = "set(FOO [=[unterminated bracket arg)"
with self.assertRaises(cmake_format.LexError) as cm:
cmake_format.format_cmake_content(code_ba)
self.assertIn("unterminated bracket argument", str(cm.exception))
def test_global_state_isolation(self):
"""Verifies custom schemas learned in File A do not leak into formatting of File B when using isolated contexts."""
file_a = (
"set(MY_CUSTOM_OPTION_ARGS OPT_ISOLATED_A OPT_ISOLATED_B)\n"
"my_custom_cmd(OPT_ISOLATED_A valA OPT_ISOLATED_B valB)\n"
)
file_b = "my_other_cmd(opt_isolated_a vala opt_isolated_b valb)\n"
ctx_a = cmake_format.FormatterContext()
ctx_b = cmake_format.FormatterContext()
cmake_format.format_cmake_content(file_a, ctx=ctx_a)
result_b = cmake_format.format_cmake_content(file_b, ctx=ctx_b)
expected_b = "my_other_cmd(opt_isolated_a vala opt_isolated_b valb)\n"
self.assertEqual(result_b, expected_b)
def test_pre_scan_workspace_modules(self):
"""Verifies pre_scan_workspace_modules discovers and scans modules in cmake/modules/."""
import tempfile
with tempfile.TemporaryDirectory() as tmpdir:
mod_dir = os.path.join(tmpdir, "cmake", "modules")
os.makedirs(mod_dir, exist_ok=True)
mod_file = os.path.join(mod_dir, "CustomModule.cmake")
with open(mod_file, "w", encoding="utf-8") as f:
f.write("set(MY_MOD_OPTION_ARGS MOD_OPT1 MOD_OPT2)\n")
ctx = cmake_format.FormatterContext()
cmake_format.pre_scan_workspace_modules([tmpdir], ctx=ctx)
self.assertIn("MOD_OPT1", ctx.learned_options)
self.assertIn("MOD_OPT2", ctx.learned_options)
def test_pre_scan_workspace_modules_fails_fast_on_error(self):
"""Verifies pre_scan_workspace_modules exits with code 1 if a module contains invalid syntax."""
import contextlib
import io
import tempfile
with tempfile.TemporaryDirectory() as tmpdir:
mod_dir = os.path.join(tmpdir, "cmake", "modules")
os.makedirs(mod_dir, exist_ok=True)
mod_file = os.path.join(mod_dir, "BrokenModule.cmake")
with open(mod_file, "w", encoding="utf-8") as f:
f.write('message("unterminated string\n')
ctx = cmake_format.FormatterContext()
err_buf = io.StringIO()
with contextlib.redirect_stderr(err_buf):
with self.assertRaises(SystemExit) as cm:
cmake_format.pre_scan_workspace_modules([tmpdir], ctx=ctx)
self.assertEqual(cm.exception.code, 1)
self.assertIn("Error pre-scanning module", err_buf.getvalue())
def test_find_cmake_files_excludes_build_directories(self):
"""Verifies find_cmake_files excludes directories starting with 'build' and '.'."""
import tempfile
with tempfile.TemporaryDirectory() as tmpdir:
for d in [
"src",
"build",
"build-ninja",
"build_debug",
".hidden",
]:
sub = os.path.join(tmpdir, d)
os.makedirs(sub, exist_ok=True)
with open(
os.path.join(sub, "CMakeLists.txt"), "w", encoding="utf-8"
) as f:
f.write("set(X 1)\n")
found = cmake_format.find_cmake_files([tmpdir])
rel_found = [os.path.relpath(p, tmpdir) for p in found]
self.assertEqual(rel_found, [os.path.join("src", "CMakeLists.txt")])
def test_stdin_pipe_formatting(self):
"""Verifies formatting unformatted CMake code via stdin."""
code = "add_library(\n foo\n STATIC\n s1.cpp\n )\n"
expected = "add_library(\n foo\n STATIC\n s1.cpp\n)\n"
self.assertEqual(cmake_format.format_cmake_content(code), expected)
class TestParsingBugs(unittest.TestCase):
"""Regression tests for parsing and formatting bugs."""
def test_bug_inline_comment_on_empty_closures(self):
"""Empty closure commands (endif, else, endfunction, etc.) preserve inline comments."""
code = "if(FOO)\n set(BAR 1)\nelse() # else comment\n set(BAR 0)\nendif() # endif comment\n"
expected = "if(FOO)\n set(BAR 1)\nelse() # else comment\n set(BAR 0)\nendif() # endif comment\n"
self.assertEqual(cmake_format.format_cmake_content(code), expected)
def test_bug_escaped_chars_in_unquoted_args(self):
"""Unquoted args containing escaped characters (e.g. \\#, \\(, \\), \\", \\ ) are preserved as single tokens."""
code = "add_entrypoint_object(\n target\n SRCS\n bar\\#baz\n bar\\(baz\\)\n C:\\Program\\ Files\\Foo\n)\n"
expected = "add_entrypoint_object(\n target\n SRCS\n bar\\#baz\n bar\\(baz\\)\n C:\\Program\\ Files\\Foo\n)\n"
self.assertEqual(cmake_format.format_cmake_content(code), expected)
def test_bug_continuation_line_starting_with_paren(self):
"""Continuation lines starting with ')' when paren balance > 0 do not prematurely close call state."""
code = "if(\n (A AND B)\n ) AND (C AND D)\n)\n set(X 1)\nendif()\n"
expected = "if(\n (A AND B)\n ) AND (C AND D)\n)\n set(X 1)\nendif()\n"
self.assertEqual(cmake_format.format_cmake_content(code), expected)
def test_bug_multiline_set_schema_learning(self):
"""Multi-line set(*_MULTI_VALUE_ARGS ...) definitions are parsed correctly by schema scanner."""
code = "set(CUSTOM_MULTI_VALUE_ARGS\n MULT_LINE1\n MULT_LINE2\n)\n"
ctx = cmake_format.FormatterContext()
cmake_format.scan_dynamic_schemas(code, ctx=ctx)
self.assertIn("MULT_LINE1", ctx.learned_multi_value)
self.assertIn("MULT_LINE2", ctx.learned_multi_value)
def test_bug_cmake_parse_arguments_var_refs(self):
"""Variable references like ${MY_OPTIONS} in cmake_parse_arguments are not registered as literal keywords."""
code = """
function(my_func)
cmake_parse_arguments("ARG" "${MY_OPTIONS}" "${MY_ONE_VAL}" "${MY_MULTI_VAL}" ${ARGN})
endfunction()
"""
ctx = cmake_format.FormatterContext()
cmake_format.scan_dynamic_schemas(code, ctx=ctx)
schema = cmake_format.get_schema_for_cmd("my_func", ctx=ctx)
self.assertNotIn("MY_OPTIONS", schema.options)
self.assertNotIn("MY_ONE_VAL", schema.one_value)
self.assertNotIn("MY_MULTI_VAL", schema.multi_value)
def test_bug_directive_comment_preservation(self):
"""Directives like #nolint, #pragma, #include, # cmake-lint, # cmake-format in comments are preserved without forced spaces."""
code = "#nolint\n#pragma once\n#include <foo>\n# cmake-lint: disable=syntax-error\n# cmake-format: off\n#cmake-lint: disable=syntax-error\n"
expected = "#nolint\n#pragma once\n#include <foo>\n# cmake-lint: disable=syntax-error\n# cmake-format: off\n#cmake-lint: disable=syntax-error\n"
self.assertEqual(cmake_format.format_cmake_content(code), expected)
if __name__ == "__main__":
unittest.main()