1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
|
# -*- coding: utf8 -*-
########################################################################################
# This file is part of exhale. Copyright (c) 2017-2024, Stephen McDowell. #
# Full BSD 3-Clause license available here: #
# #
# https://github.com/svenevs/exhale/blob/master/LICENSE #
########################################################################################
"""
Tests for the ``cpp_long_names`` project.
"""
from __future__ import unicode_literals
import hashlib
import os
import platform
import shutil
import textwrap
from exhale.configs import MAXIMUM_FILENAME_LENGTH
import pytest
from testing import TEST_PROJECTS_ROOT
from testing.base import ExhaleTestCase
from testing.hierarchies import compare_file_hierarchy, file_hierarchy
from testing.projects.cpp_long_names import \
ABSURD_DIRECTORY_PATH, RUN_ABSURD_TEST, make_it_big
def create_absurd_directory_structure():
"""
Create the absurd directory structure when |RUN_ABSURD_TEST| is ``True``.
Helper function for the testing fixture :func:`potentially_with_insanity_fixture`.
.. |RUN_ABSURD_TEST| replace:: :data:`testing.projects.cpp_long_names.RUN_ABSURD_TEST`
"""
if RUN_ABSURD_TEST:
try:
absurd_dir = ABSURD_DIRECTORY_PATH
if not os.path.isdir(absurd_dir):
os.makedirs(absurd_dir)
with open(os.path.join(absurd_dir, "a_file.hpp"), "w") as a_file:
a_file.write(textwrap.dedent(r'''
/***************************************************************************************
* This file is dedicated to the public domain. If your jurisdiction requires a *
* specific license: *
* *
* Copyright (c) Stephen McDowell, 2017-2024 *
* License: CC0 1.0 Universal *
* License Text: https://creativecommons.org/publicdomain/zero/1.0/legalcode *
**************************************************************************************/
/** \file */
#pragma once
#include <string>
/// A function from an extremely nested file path.
inline std::string extremely_nested() {
return "Extremely nested works!!!";
}
'''))
except Exception as e:
raise RuntimeError(
"Could not make the absurd directory structure: {0}".format(e)
)
def remove_absurd_directory_structure():
"""
Remove the absurd directory structure when |RUN_ABSURD_TEST| is ``True``.
Helper function for the testing fixture :func:`potentially_with_insanity_fixture`.
"""
if RUN_ABSURD_TEST:
absurd_dir_root = os.path.abspath(os.path.join(
TEST_PROJECTS_ROOT,
"cpp_long_names",
"include",
"directory"
))
try:
if os.path.isdir(absurd_dir_root):
shutil.rmtree(absurd_dir_root)
except Exception as e:
raise RuntimeError("Could not remove the directory [{0}]: {1}".format(
absurd_dir_root, e
))
@pytest.fixture(scope="class")
def potentially_with_insanity_fixture():
"""
Class-level fixture that may create / remove the absurd directory.
This will create the absurd directory structure before any tests are run, and
remove it when all are finished when |RUN_ABSURD_TEST| is ``True``.
"""
create_absurd_directory_structure()
yield
remove_absurd_directory_structure()
def potentially_with_insanity(cls):
"""
Mark ``cls`` to use the fixture :func:`potentially_with_insanity`.
**Parameters**
``cls`` (:class:`~testing.tests.cpp_long_names.CPPLongNames`)
Decorator designed **only** for :class:`~testing.tests.cpp_long_names.CPPLongNames`.
**Return** (:class:`~testing.tests.cpp_long_names.CPPLongNames`)
The input ``cls``, after executing ``pytest.mark.usefixtures``.
"""
pytest.mark.usefixtures("potentially_with_insanity_fixture")(cls)
return cls
@potentially_with_insanity
class CPPLongNames(ExhaleTestCase):
"""
Primary test class for project ``cpp_long_names``.
"""
test_project = "cpp_long_names"
""".. testproject:: cpp_long_names"""
def test_hashes(self):
"""Verify the long names get hashed to the expected values."""
# Make sure that the generated files and such _actually_ work via Sphinx.
# NOTE: Sphinx actually crashes for the same reasons Exhale was on Windows
# because they do not prefix with \\?\ for >= 260 length paths x0
if platform.system() != "Windows":
self.app.build()
# Define a testing function that will check either:
#
# 1. file_name does exist and hash_name does not, or
# 2. file_name does not exist and hash_name does
#
# Which will depend on the length of file_name.
containment_folder = self.getAbsContainmentFolder()
def check_both(file_name, hash_name):
# Setup for binding local functions.
if len(file_name) >= MAXIMUM_FILENAME_LENGTH:
file_name_exists = "assertFalse"
file_name_notice = "[{path}] should *NOT* exist but did."
hash_name_exists = "assertTrue"
hash_name_notice = "[{path}] *SHOULD* exist but did not."
else:
file_name_exists = "assertTrue"
file_name_notice = "[{path}] *SHOULD* exist but did not."
hash_name_exists = "assertFalse"
hash_name_notice = "[{path}] should *NOT* exist but did."
# Bind some local functions (to this local function LOL).
check_file_name = getattr(self, file_name_exists)
check_hash_name = getattr(self, hash_name_exists)
# Create the absolute paths to the files to check.
file_path = os.path.join(containment_folder, file_name)
hash_path = os.path.join(containment_folder, hash_name)
# Verify that either the regular name exists and the hash does not, or vice-versa.
check_file_name(
os.path.isfile(file_path), file_name_notice.format(path=file_path)
)
check_hash_name(
os.path.isfile(hash_path), hash_name_notice.format(path=hash_path)
)
if RUN_ABSURD_TEST:
# Verify that the generated directories are correct, including getting a
# sha1 sum once the full path is longer than 255 characters.
long_dirs = make_it_big("include_directory_structure").split("_")
curr_dir = "dir"
for d in long_dirs:
# Synthetic setup to graph.ExhaleRoot.initializeNodeFilenameAndLink
curr_dir = "{curr_dir}_{d}".format(curr_dir=curr_dir, d=d)
link_name = curr_dir
# Set both names to check and make sure that only one exists.
file_name = "{link_name}.rst".format(link_name=link_name)
hash_name = "dir_{sha1}.rst".format(
sha1=hashlib.sha1(link_name.encode()).hexdigest()
)
check_both(file_name, hash_name)
# Verify that the file a_file.hpp also uses the hashed name since it's full
# path will be too long.
long_dirs.append("a_file.hpp")
link_name = "file_{path}".format(path="_".join(long_dirs))
file_name = "{link_name}.rst".format(link_name=link_name)
hash_name = "file_{sha1}.rst".format(
sha1=hashlib.sha1(link_name.encode()).hexdigest()
)
check_both(file_name, hash_name)
# Repeat for the program listing of a_file.hpp
file_name = "program_listing_{file_name}".format(file_name=file_name)
hash_name = "program_listing_{hash_name}".format(hash_name=hash_name)
check_both(file_name, hash_name)
# Besides files and directories, the only other compounds that do not use the
# Doxygen refid's (Doxygen also uses hashing to shorten) in Exhale are
# namespaces, so this is the last one to check.
namespace = make_it_big("namespace")
link_name = "namespace_{namespace}".format(namespace=namespace)
file_name = "{link_name}.rst".format(link_name=link_name)
hash_name = "namespace_{sha1}.rst".format(
sha1=hashlib.sha1(link_name.encode()).hexdigest()
)
check_both(file_name, hash_name)
def test_file_hierarchy(self):
"""
Verify the file hierarchy.
The class hierarchy is not validated for this test project simply because doing
so is rather pointless, and the added complexity to do so given the
conditionally created structure is not worth the effort.
"""
compare_file_hierarchy(self, file_hierarchy(self.file_hierarchy_dict()))
|