Skip to content

Commit

Permalink
Document CTest add_test() (#128)
Browse files Browse the repository at this point in the history
* update VERSION.txt

* update VERSION.txt

* Add CTest add_test() processor and documentation type

* Add config options for documenting undocumented add_test() invocations

* Delete VERSION.txt

* Add tests for documenting CTest tests

* Add sample and corr RST for ctest add_test

* Add documentation for documenting ctest add_test()

* Add test for incorrect ctest add_test params

* Add additional error checking test for documenting ctest add_test()

* Fix minor comment issue

Co-authored-by: cmakepp[bot] <cmakepp[bot]@github.com>
Co-authored-by: Ryan Richard <[email protected]>
  • Loading branch information
3 people authored Sep 19, 2022
1 parent b6436f0 commit 7184b41
Show file tree
Hide file tree
Showing 16 changed files with 249 additions and 4 deletions.
31 changes: 31 additions & 0 deletions docs/source/documenting/ctest_add_test.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
.. Copyright 2021 CMakePP
..
.. Licensed 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.
..
############################
Documenting a CTest Test
############################

CMinx can be used to document a CTest test created by the
`add_test() <https://cmake.org/cmake/help/latest/command/add_test.html>`_ command.
Again, this is done analogous to other documentation use cases, *i.e.*, by
proceeding the ``add_test()`` command with a
documentation comment. For example,

.. literalinclude:: ../../../tests/test_samples/ctest_add_test.cmake
:language: cmake

which generates:

.. literalinclude:: ../../../tests/test_samples/corr_rst/ctest_add_test.rst
:language: rst
39 changes: 38 additions & 1 deletion src/cminx/aggregator.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

from .documentation_types import AttributeDocumentation, FunctionDocumentation, MacroDocumentation, \
VariableDocumentation, GenericCommandDocumentation, ClassDocumentation, TestDocumentation, SectionDocumentation, \
MethodDocumentation, VarType
MethodDocumentation, VarType, CTestDocumentation
from .parser.CMakeListener import CMakeListener
# Annoyingly, the Antl4 Python libraries use camelcase since it was originally Java, so we have convention
# inconsistencies here
Expand Down Expand Up @@ -363,6 +363,43 @@ def process_cpp_attr(self, ctx: CMakeParser.Command_invocationContext, docstring
clazz.attributes.append(AttributeDocumentation(
name, docstring, parent_class, default_values))

def process_add_test(self, ctx: CMakeParser.Command_invocationContext, docstring: str):
"""
Extracts information from a CTest add_test() command.
Note: this is not the processor for the CMakeTest ct_add_test() command,
but the processor for the vanilla CMake add_test() command.
:param ctx: Documented command context. Constructed by the Antlr4 parser.
:param docstring: Cleaned docstring.
"""
params = [param.getText() for param in ctx.single_argument()] # Extract parameters

if len(params) < 2:
pretty_text = docstring
pretty_text += f"\n{ctx.getText()}"

self.logger.error(
f"ct_add_section() called with incorrect parameters: {params}\n\n{pretty_text}")
return

name = ""
for i in range(0, len(params)):
param = params[i]
if param.upper() == "NAME":
try:
name = params[i + 1]
except IndexError:
pretty_text = docstring
pretty_text += f"\n{ctx.getText()}"

self.logger.error(f"add_test() called with incorrect parameters: {params}\n\n{pretty_text}")
return

test_doc = CTestDocumentation(name, docstring, filter(lambda p: p != name and p != "NAME", params))
self.documented.append(test_doc)
self.documented_awaiting_function_def = test_doc

def process_generic_command(self, command_name: str, ctx: CMakeParser.Command_invocationContext, docstring: str):
"""
Extracts command invocation and arguments for a documented command that does not
Expand Down
2 changes: 2 additions & 0 deletions src/cminx/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ def config_template(output_dir_relative_to_config: bool = False) -> dict:
"include_undocumented_cpp_constructor": bool,
"include_undocumented_cpp_member": bool,
"include_undocumented_ct_add_test": bool,
"include_undocumented_add_test": bool,
"include_undocumented_ct_add_section": bool,
"auto_exclude_directories_without_cmake": bool,
"exclude_filters": confuse.Optional(list, default=()),
Expand Down Expand Up @@ -68,6 +69,7 @@ class InputSettings:
include_undocumented_cpp_member: bool = True
include_undocumented_ct_add_test: bool = True
include_undocumented_ct_add_section: bool = True
include_undocumented_add_test: bool = True
auto_exclude_directories_without_cmake: bool = True
exclude_filters: List[str] = ()
recursive: bool = False
Expand Down
6 changes: 6 additions & 0 deletions src/cminx/config_default.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ input:
# auto-generated.
include_undocumented_ct_add_section: true

# Whether undocumented CTest tests should have documentation
# auto-generated. This controls whether all vanilla
# CMake add_test() commands should be documented,
# it has no relation to CMakeTest tests.
include_undocumented_add_test: true

# Whether directories not containing .cmake
# files should be excluded from recursive mode searching.
auto_exclude_directories_without_cmake: true
Expand Down
22 changes: 22 additions & 0 deletions src/cminx/documentation_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,28 @@ def process(self, writer: RSTWriter):
d.text(self.doc)


@dataclass
class CTestDocumentation(DocumentationType):
"""
This dataclass holds documentation information
for a vanilla CTest test. These tests are created
with the "add_test()" command from regular
CMake, and documenting such a call will
create this type of documentation.
"""
params: List[str] = field(default_factory=lambda: [])

def process(self, writer: RSTWriter):
d = writer.directive(
"function",
f"{self.name}({' '.join(self.params)})")
d.directive(
"warning",
'This is a CTest test definition, do not call this manually. '
'Use the "ctest" program to execute this test.')
d.text(self.doc)


@dataclass
class TestDocumentation(DocumentationType):
"""
Expand Down
8 changes: 7 additions & 1 deletion tests/examples/configs/no_include_undocumented_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,10 @@ input:

# Whether undocumented test sections should have documentation
# auto-generated.
include_undocumented_ct_add_section: false
include_undocumented_ct_add_section: false

# Whether undocumented CTest tests should have documentation
# auto-generated. This controls whether all vanilla
# CMake add_test() commands should be documented,
# it has no relation to CMakeTest tests.
include_undocumented_add_test: false
23 changes: 23 additions & 0 deletions tests/examples/example.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -251,3 +251,26 @@ function("${undocumented_test}")
endfunction()

endfunction()

#[[[
# This is a documented CTest test.
# Note that this is a vanilla CMake
# add_test() command, not a ct_add_test()
# command
#]]
add_test(
NAME ctest_test
COMMAND bash -c echo test
)

#[[
# This is an udocumented CTest test.
# Note that this is a vanilla CMake
# add_test() command, not a ct_add_test()
# command
#]]
add_test(
NAME ctest_test_undocumented
COMMAND bash -c echo test
)

20 changes: 20 additions & 0 deletions tests/examples/sphinx/source/example.rst
Original file line number Diff line number Diff line change
Expand Up @@ -313,3 +313,23 @@ examples.example




.. function:: ctest_test(COMMAND bash -c echo test)


.. warning:: This is a CTest test definition, do not call this manually. Use the "ctest" program to execute this test.

This is a documented CTest test.
Note that this is a vanilla CMake
add_test() command, not a ct_add_test()
command



.. function:: ctest_test_undocumented(COMMAND bash -c echo test)


.. warning:: This is a CTest test definition, do not call this manually. Use the "ctest" program to execute this test.



12 changes: 12 additions & 0 deletions tests/examples/sphinx/source/example_no_undocumented.rst
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,15 @@ examples.example
This is a nested class



.. function:: ctest_test(COMMAND bash -c echo test)


.. warning:: This is a CTest test definition, do not call this manually. Use the "ctest" program to execute this test.

This is a documented CTest test.
Note that this is a vanilla CMake
add_test() command, not a ct_add_test()
command


Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,15 @@ examples.example.cmake
This is a nested class



.. function:: ctest_test(COMMAND bash -c echo test)


.. warning:: This is a CTest test definition, do not call this manually. Use the "ctest" program to execute this test.

This is a documented CTest test.
Note that this is a vanilla CMake
add_test() command, not a ct_add_test()
command


20 changes: 20 additions & 0 deletions tests/examples/sphinx/source/example_prefix.rst
Original file line number Diff line number Diff line change
Expand Up @@ -313,3 +313,23 @@ prefix.example




.. function:: ctest_test(COMMAND bash -c echo test)


.. warning:: This is a CTest test definition, do not call this manually. Use the "ctest" program to execute this test.

This is a documented CTest test.
Note that this is a vanilla CMake
add_test() command, not a ct_add_test()
command



.. function:: ctest_test_undocumented(COMMAND bash -c echo test)


.. warning:: This is a CTest test definition, do not call this manually. Use the "ctest" program to execute this test.



18 changes: 18 additions & 0 deletions tests/test_samples/corr_rst/ctest_add_test.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

###########################
test_samples.ctest_add_test
###########################

.. module:: test_samples.ctest_add_test


.. function:: example_test(COMMAND echo hello WORKING_DIRECTORY build/)


.. warning:: This is a CTest test definition, do not call this manually. Use the "ctest" program to execute this test.

This is how to document a CTest test.
Note that this is not a CMakeTest,
but rather a vanilla CMake add_test() command.


10 changes: 10 additions & 0 deletions tests/test_samples/ctest_add_test.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#[[[
# This is how to document a CTest test.
# Note that this is not a CMakeTest,
# but rather a vanilla CMake add_test() command.
#]]
add_test(
NAME example_test
COMMAND echo hello
WORKING_DIRECTORY build/
)
22 changes: 22 additions & 0 deletions tests/unit_tests/test_aggregator.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,28 @@ def test_invalid_ct_add_section_params(self):
self.assertEqual(0, len(self.aggregator.documented),
f"Incorrect {command_name}() call was still added to documented list: {self.aggregator.documented}")

def test_invalid_ctest_add_test_params(self):
docstring = "This is documentation for an incorrect ct_add_section() call"
# add_test() requires two params minimum
params = ["NAME"]
command_name = "add_test"
command = f'{command_name}({" ".join(params)})'
self.input_stream = InputStream(f'#[[[\n{docstring}\n#]]\n{command}')
self.reset()
self.assertEqual(0, len(self.aggregator.documented),
f"Incorrect {command_name}() call was still added to documented list: {self.aggregator.documented}")

def test_incorrect_ctest_add_test_params(self):
docstring = "This is documentation for an incorrect ct_add_section() call"
# add_test() requires an additional param after NAME, not before
params = ["blah", "NAME"]
command_name = "add_test"
command = f'{command_name}({" ".join(params)})'
self.input_stream = InputStream(f'#[[[\n{docstring}\n#]]\n{command}')
self.reset()
self.assertEqual(0, len(self.aggregator.documented),
f"Incorrect {command_name}() call was still added to documented list: {self.aggregator.documented}")

def test_incorrect_set_params(self):
docstring = "This is documentation for an incorrect set() call"
params = []
Expand Down
5 changes: 4 additions & 1 deletion tests/unit_tests/test_documenter.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

from cminx.documenter import Documenter
from cminx.documentation_types import FunctionDocumentation, MacroDocumentation, VariableDocumentation, \
GenericCommandDocumentation, ClassDocumentation, TestDocumentation, SectionDocumentation
GenericCommandDocumentation, ClassDocumentation, TestDocumentation, SectionDocumentation, CTestDocumentation
from cminx.rstwriter import Directive, RSTWriter


Expand Down Expand Up @@ -64,6 +64,9 @@ def test_process(self):
elif isinstance(doc, SectionDocumentation):
self.assertIsInstance(element, Directive, "Wrong RST element generated for test section")
self.assertEqual("function", element.document[0].title, "Wrong directive type for test section")
elif isinstance(doc, CTestDocumentation):
self.assertIsInstance(element, Directive, "Wrong RST element generated for CTest test")
self.assertEqual("function", element.document[0].title, "Wrong directive type for CTest test")
else:
self.fail(f"Unknown documentation type: {doc}")

Expand Down
3 changes: 2 additions & 1 deletion tests/unit_tests/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ def test_header_extensions_no_undocumented_diff_header(self):
input_settings = InputSettings(include_undocumented_ct_add_test=False, include_undocumented_cpp_attr=False,
include_undocumented_function=False, include_undocumented_cpp_class=False,
include_undocumented_macro=False, include_undocumented_cpp_member=False,
include_undocumented_ct_add_section=False, recursive=True)
include_undocumented_ct_add_section=False, include_undocumented_add_test=False,
recursive=True)
output_settings = OutputSettings(directory=self.output_dir)
rst_settings = RSTSettings(file_extensions_in_modules=True, file_extensions_in_titles=True,
headers=['^', '*', '=', '-', '_', '~', '!', '&', '@'])
Expand Down

0 comments on commit 7184b41

Please sign in to comment.