Skip to content

Commit 12e7ccd

Browse files
committed
Enhancement: add setup.py and tests
1 parent eeef214 commit 12e7ccd

File tree

6 files changed

+811
-0
lines changed

6 files changed

+811
-0
lines changed

pytest.ini

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[pytest]
2+
testpaths =
3+
tests
4+
norecursedirs=.git GDBKokkos
5+
addopts =
6+
--doctest-modules
7+
--cov=GDBKokkos
8+
-r a
9+
-v

setup.py

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#! /usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
# vim:fenc=utf-8
4+
#
5+
# Copyright 2020 Char Aznable <[email protected]>
6+
# Description: Utilities for pretty-printing Kokkos::View
7+
#
8+
# Distributed under terms of the 3-clause BSD license.
9+
import setuptools
10+
11+
setuptools.setup(
12+
name="GDBKokkos",
13+
python_requires=">=3.8.5",
14+
version="0.0.1",
15+
description="GDB python modules for debugging Kokkos",
16+
long_description="see https://github.com/Char-Aznable/GDBKokkos",
17+
long_description_content_type="text/markdown",
18+
url="https://github.com/Char-Aznable/GDBKokkos.git",
19+
author="Char Aznable",
20+
author_email="[email protected]",
21+
license="BSD 3-clause",
22+
classifiers=[
23+
"License :: OSI Approved :: BSD License",
24+
"Programming Language :: Python",
25+
"Programming Language :: Python :: 3",
26+
],
27+
packages=["GDBKokkos"],
28+
include_package_data=True,
29+
install_requires=[
30+
"numpy",
31+
"pandas",
32+
],
33+
extras_require = {
34+
"tests" : ["pytest", "pytest-cov", "codecov",
35+
"cmake", "ninja"]
36+
},
37+
data_files = [("", ["LICENSE"])]
38+
)

tests/conftest.py

+104
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
#! /usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
# vim:fenc=utf-8
4+
#
5+
# Copyright 2020 Char Aznable <[email protected]>
6+
# Description: Utilities for pretty-printing Kokkos::View
7+
#
8+
# Distributed under terms of the 3-clause BSD license.
9+
import re
10+
import subprocess
11+
import pytest
12+
import textwrap
13+
14+
@pytest.fixture(scope="module")
15+
def writeCPP(tmpdir_factory, request):
16+
"""Write a c++ source file for gdb to examine the Kokkos::View
17+
18+
Args:
19+
tmpdir_factory (TempdirFactory): pytest fixture for generating a
20+
temporary directory and file
21+
22+
Returns: TODO
23+
24+
"""
25+
shape = getattr(request.module, "shape", (3,4,5))
26+
layout = getattr(request.module, "layout", "Kokkos::LayoutRight")
27+
cpp = getattr(request.module, "cpp", "")
28+
fnShape = "-".join(map(str, shape))
29+
fnLayout = re.sub(r"::", "", layout)
30+
p = tmpdir_factory.mktemp(f"TestView{fnLayout}{fnShape}")
31+
fCXX = p.join("test.cpp")
32+
fCXX.write(textwrap.dedent(cpp))
33+
yield (p, fCXX)
34+
35+
36+
@pytest.fixture(scope="module")
37+
def generateCMakeProject(writeCPP):
38+
p, _ = writeCPP
39+
fCMakeLists = p.join("CMakeLists.txt")
40+
fCMakeLists.write(textwrap.dedent(
41+
"""
42+
cmake_minimum_required(VERSION 3.14)
43+
project(testLayoutRight CXX)
44+
include(FetchContent)
45+
46+
FetchContent_Declare(
47+
kokkos
48+
GIT_REPOSITORY https://github.com/kokkos/kokkos.git
49+
GIT_TAG origin/develop
50+
GIT_SHALLOW 1
51+
GIT_PROGRESS ON
52+
)
53+
54+
FetchContent_MakeAvailable(kokkos)
55+
56+
aux_source_directory(${CMAKE_CURRENT_LIST_DIR} testSources)
57+
58+
foreach(testSource ${testSources})
59+
get_filename_component(testBinary ${testSource} NAME_WE)
60+
add_executable(${testBinary} ${testSource})
61+
target_include_directories(${testBinary} PRIVATE ${CMAKE_CURRENT_LIST_DIR})
62+
target_link_libraries(${testBinary} kokkos)
63+
add_test(NAME ${testBinary} COMMAND ${testBinary})
64+
endforeach()
65+
"""
66+
))
67+
fBuildDir = p.mkdir("build")
68+
with fBuildDir.as_cwd():
69+
cmdCmake = [f"cmake {fCMakeLists.dirpath().strpath} "
70+
f"-DCMAKE_CXX_COMPILER=g++ "
71+
f"-DCMAKE_CXX_STANDARD=14 "
72+
f"-DCMAKE_CXX_FLAGS='-DDEBUG -O0 -g' "
73+
f"-DCMAKE_VERBOSE_MAKEFILE=ON "
74+
]
75+
rCmake = subprocess.run(cmdCmake, shell=True, capture_output=True,
76+
encoding='utf-8')
77+
assert rCmake.returncode == 0, f"Error with running cmake: {rCmake.stderr}"
78+
cmdMake = [f"make -j"]
79+
rMake = subprocess.run(cmdMake, shell=True, capture_output=True,
80+
encoding='utf-8')
81+
assert rMake.returncode == 0, f"Error with running make: {rMake.stderr}"
82+
fTest = fBuildDir.join("test")
83+
yield (p, fBuildDir, fTest)
84+
85+
86+
@pytest.fixture
87+
def runGDB():
88+
def _runGDB(content : str, fPath, executable : str):
89+
fPath.write(textwrap.dedent(content))
90+
cmd = [f"gdb -batch "
91+
f"{executable} "
92+
f"-x {fPath.realpath().strpath}"
93+
]
94+
r = subprocess.run(cmd,
95+
shell=True,
96+
capture_output=True,
97+
encoding='utf-8'
98+
)
99+
assert r.returncode == 0,f"GDB error: {r.stderr}"
100+
# Get the output from GDB since the last breakpoint mark
101+
return (r,
102+
re.compile(r"\s*\d+\s*breakpoint\(\)\s*;\s*\n").split(r.stdout)[1].strip())
103+
return _runGDB
104+

tests/test_LayoutLeft.py

+227
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
#! /usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
# vim:fenc=utf-8
4+
#
5+
# Copyright 2020 Char Aznable <[email protected]>
6+
# Description: Utilities for pretty-printing Kokkos::View
7+
#
8+
# Distributed under terms of the 3-clause BSD license.
9+
import re
10+
import numpy as np
11+
12+
shape = (3, 4, 5)
13+
strShape = ",".join(map(str, shape))
14+
layout = "Kokkos::LayoutLeft"
15+
span = np.array(shape).prod()
16+
cpp = f"""
17+
#include <Kokkos_Core.hpp>
18+
19+
void breakpoint() {{ return; }}
20+
21+
int main(int argc, char* argv[]) {{
22+
Kokkos::initialize(argc,argv); {{
23+
24+
Kokkos::View<float***,{layout}> v("v",{strShape});
25+
26+
Kokkos::parallel_for(v.span(), KOKKOS_LAMBDA (const int i)
27+
{{ *(v.data()+i) = i; }});
28+
29+
breakpoint();
30+
31+
}} Kokkos::finalize();
32+
33+
}}
34+
"""
35+
36+
def testLayout(generateCMakeProject, runGDB):
37+
p, _, fTest = generateCMakeProject
38+
fGDB = p.join("testLayout.gdbinit")
39+
r, resultStr = runGDB(
40+
"""
41+
py from GDBKokkos.printView import getKokkosViewLayout
42+
set confirm off
43+
44+
b breakpoint()
45+
commands
46+
silent
47+
frame 1
48+
end
49+
50+
run
51+
52+
py v = gdb.parse_and_eval('v')
53+
py print(getKokkosViewLayout(v))
54+
quit
55+
56+
""",
57+
fGDB, f"{fTest.realpath().strpath}"
58+
)
59+
assert resultStr == layout, f"Wrong output layout: {r.stdout}"
60+
61+
62+
def testExtent(generateCMakeProject, runGDB):
63+
p, _, fTest = generateCMakeProject
64+
fGDB = p.join("testExtent.gdbinit")
65+
r, resultStr = runGDB(
66+
"""
67+
py from GDBKokkos.printView import getKokkosViewExtent
68+
set confirm off
69+
70+
b breakpoint()
71+
commands
72+
silent
73+
frame 1
74+
end
75+
76+
run
77+
78+
py v = gdb.parse_and_eval('v')
79+
py print(getKokkosViewExtent(v))
80+
quit
81+
82+
""",
83+
fGDB, f"{fTest.realpath().strpath}"
84+
)
85+
result = np.array(re.sub(r"\D+", " ", resultStr).split(), dtype=int)
86+
assert (result == np.array(shape)).all(), f"Wrong output extent: {r.stdout}"
87+
88+
89+
def testStrides(generateCMakeProject, runGDB):
90+
p, _, fTest = generateCMakeProject
91+
fGDB = p.join("testExtent.gdbinit")
92+
r, resultStr = runGDB(
93+
"""
94+
py from GDBKokkos.printView import getKokkosViewStrides
95+
set confirm off
96+
97+
b breakpoint()
98+
commands
99+
silent
100+
frame 1
101+
end
102+
103+
run
104+
105+
py v = gdb.parse_and_eval('v')
106+
py print(getKokkosViewStrides(v))
107+
quit
108+
109+
""",
110+
fGDB, f"{fTest.realpath().strpath}"
111+
)
112+
result = np.array(re.sub(r"\D+", " ", resultStr).split(), dtype=int)
113+
expected = np.ones_like(shape, dtype=int)
114+
expected[1:] = shape[:-1]
115+
expected = np.cumprod(expected)
116+
assert (result == expected).all(), f"Wrong output strides: {r.stdout}"
117+
118+
119+
def testTraits(generateCMakeProject, runGDB):
120+
p, _, fTest = generateCMakeProject
121+
fGDB = p.join("testTraits.gdbinit")
122+
r, resultStr = runGDB(
123+
"""
124+
py from GDBKokkos.printView import getKokkosViewTraits
125+
set confirm off
126+
127+
b breakpoint()
128+
commands
129+
silent
130+
frame 1
131+
end
132+
133+
run
134+
135+
py v = gdb.parse_and_eval('v')
136+
py print(getKokkosViewTraits(v))
137+
quit
138+
139+
""",
140+
fGDB, f"{fTest.realpath().strpath}"
141+
)
142+
assert resultStr == f"Kokkos::ViewTraits<float***, {layout}>",\
143+
"Wrong output traits: {r.stdout}"
144+
145+
146+
def testValueType(generateCMakeProject, runGDB):
147+
p, _, fTest = generateCMakeProject
148+
fGDB = p.join("testValueType.gdbinit")
149+
r, resultStr = runGDB(
150+
"""
151+
py from GDBKokkos.printView import getKokkosViewValueType
152+
set confirm off
153+
154+
b breakpoint()
155+
commands
156+
silent
157+
frame 1
158+
end
159+
160+
run
161+
162+
py v = gdb.parse_and_eval('v')
163+
py print(getKokkosViewValueType(v))
164+
quit
165+
166+
""",
167+
fGDB, f"{fTest.realpath().strpath}"
168+
)
169+
assert resultStr == f"float",\
170+
"Wrong output ValueType: {r.stdout}"
171+
172+
173+
def testSpan(generateCMakeProject, runGDB):
174+
p, _, fTest = generateCMakeProject
175+
fGDB = p.join("testSpan.gdbinit")
176+
r, resultStr = runGDB(
177+
"""
178+
py from GDBKokkos.printView import getKokkosViewSpan
179+
set confirm off
180+
181+
b breakpoint()
182+
commands
183+
silent
184+
frame 1
185+
end
186+
187+
run
188+
189+
py v = gdb.parse_and_eval('v')
190+
py print(getKokkosViewSpan(v))
191+
quit
192+
193+
""",
194+
fGDB, f"{fTest.realpath().strpath}"
195+
)
196+
assert int(resultStr) == np.array(shape).prod(),\
197+
"Wrong output Span: {r.stdout}"
198+
199+
200+
def testPrintView(generateCMakeProject, runGDB):
201+
p, _, fTest = generateCMakeProject
202+
fGDB = p.join("testPrintView.gdbinit")
203+
r, resultStr = runGDB(
204+
"""
205+
py import GDBKokkos
206+
set confirm off
207+
208+
b breakpoint()
209+
commands
210+
silent
211+
frame 1
212+
end
213+
214+
run
215+
216+
printView v --noIndex
217+
quit
218+
219+
""",
220+
fGDB, f"{fTest.realpath().strpath}"
221+
)
222+
223+
result = np.array(resultStr.split()).astype(float).reshape(shape)
224+
expected = np.arange(span).astype(float).reshape(shape, order='F')
225+
assert (result == expected).all(),\
226+
f"printView gives wrong view of shape {tuple}: {r.stdout}. Expected:\n"\
227+
f"{expected}"

0 commit comments

Comments
 (0)