aboutsummaryrefslogtreecommitdiff
path: root/pw_presubmit/py/cpp_checks_test.py
diff options
context:
space:
mode:
Diffstat (limited to 'pw_presubmit/py/cpp_checks_test.py')
-rw-r--r--pw_presubmit/py/cpp_checks_test.py125
1 files changed, 125 insertions, 0 deletions
diff --git a/pw_presubmit/py/cpp_checks_test.py b/pw_presubmit/py/cpp_checks_test.py
new file mode 100644
index 000000000..77e448227
--- /dev/null
+++ b/pw_presubmit/py/cpp_checks_test.py
@@ -0,0 +1,125 @@
+#!/usr/bin/env python3
+# Copyright 2023 The Pigweed Authors
+#
+# 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
+#
+# https://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.
+"""Tests for cpp_checks."""
+
+import os
+from pathlib import Path
+import unittest
+from unittest.mock import MagicMock, mock_open, patch
+
+from pw_presubmit import cpp_checks
+
+# pylint: disable=attribute-defined-outside-init
+
+
+def _temproot():
+ root = Path(os.environ['_PW_ACTUAL_ENVIRONMENT_ROOT']) / 'temp'
+ root.mkdir(exist_ok=True)
+ return root
+
+
+class TestPragmaOnce(unittest.TestCase):
+ """Test pragma_once check."""
+
+ def _run(self, contents: str) -> None:
+ self.ctx = MagicMock()
+ self.ctx.fail = MagicMock()
+ self.ctx.format_options.filter_paths = lambda x: x
+ path = MagicMock(spec=Path('include/foo.h'))
+
+ def mocked_open_read(*args, **kwargs):
+ return mock_open(read_data=contents)(*args, **kwargs)
+
+ with patch.object(path, 'open', mocked_open_read):
+ self.ctx.paths = [path]
+ cpp_checks.pragma_once(self.ctx)
+
+ def test_empty(self) -> None:
+ self._run('')
+ self.ctx.fail.assert_called()
+
+ def test_simple(self) -> None:
+ self._run('#pragma once')
+ self.ctx.fail.assert_not_called()
+
+ def test_not_first(self) -> None:
+ self._run('1\n2\n3\n#pragma once')
+ self.ctx.fail.assert_not_called()
+
+ def test_different_pragma(self) -> None:
+ self._run('#pragma thrice')
+ self.ctx.fail.assert_called()
+
+
+def guard(path: Path) -> str:
+ return str(path.name).replace('.', '_').upper()
+
+
+class TestIncludeGuard(unittest.TestCase):
+ """Test pragma_once check."""
+
+ def _run(self, contents: str, **kwargs) -> None:
+ self.ctx = MagicMock()
+ self.ctx.format_options.filter_paths = lambda x: x
+ self.ctx.fail = MagicMock()
+ path = MagicMock(spec=Path('abc/def/foo.h'))
+ path.name = 'foo.h'
+
+ def mocked_open_read(*args, **kwargs):
+ return mock_open(read_data=contents)(*args, **kwargs)
+
+ with patch.object(path, 'open', mocked_open_read):
+ self.ctx.paths = [path]
+ check = cpp_checks.include_guard_check(**kwargs)
+ check(self.ctx)
+
+ def test_empty(self) -> None:
+ self._run('')
+ self.ctx.fail.assert_called()
+
+ def test_simple(self) -> None:
+ self._run('#ifndef FOO_H\n#define FOO_H', guard=guard)
+ self.ctx.fail.assert_not_called()
+
+ def test_simple_any(self) -> None:
+ self._run('#ifndef BAR_H\n#define BAR_H')
+ self.ctx.fail.assert_not_called()
+
+ def test_simple_comments(self) -> None:
+ self._run('// abc\n#ifndef BAR_H\n// def\n#define BAR_H\n// ghi')
+ self.ctx.fail.assert_not_called()
+
+ def test_simple_whitespace(self) -> None:
+ self._run(
+ ' // abc\n #ifndef BAR_H\n// def\n'
+ ' #define BAR_H\n// ghi\n #endif'
+ )
+ self.ctx.fail.assert_not_called()
+
+ def test_simple_not_expected(self) -> None:
+ self._run('#ifnef BAR_H\n#define BAR_H', guard=guard)
+ self.ctx.fail.assert_called()
+
+ def test_no_define(self) -> None:
+ self._run('#ifndef FOO_H')
+ self.ctx.fail.assert_called()
+
+ def test_non_matching_define(self) -> None:
+ self._run('#ifndef FOO_H\n#define BAR_H')
+ self.ctx.fail.assert_called()
+
+
+if __name__ == '__main__':
+ unittest.main()