Skip to content

Commit ba427e7

Browse files
committed
Switch from nose2 to pytest for tests
1 parent 74150e7 commit ba427e7

11 files changed

+767
-678
lines changed

.github/workflows/tests.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,9 @@ jobs:
3030
- name: Check lockfile
3131
run: uv lock --check
3232

33-
- name: Test with nose2
33+
- name: Test with pytest
3434
run: |
35-
uv run coverage run -m nose2
36-
uv run coverage lcov -o cover/coverage.lcov
35+
uv run pytest --cov --cov-report=lcov:cover/coverage.lcov --cov-report=term-missing
3736
3837
- name: Coveralls
3938
uses: coverallsapp/github-action@master

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ module-root = ""
3333
[dependency-groups]
3434
dev = [
3535
"coverage==7.6.10",
36-
"nose2==0.15.1",
36+
"pytest>=8.4.2",
37+
"pytest-cov>=6.3.0",
3738
"ruff==0.12.0",
3839
"tomli==2.2.1",
3940
"typing-extensions==4.12.2",

tests/test_simulator_display.py

Lines changed: 150 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -2,165 +2,166 @@
22

33
import contextlib
44
import io
5-
import unittest
5+
import re
66

77
from cachesimulator.simulator import Simulator
88

99
WORD_ADDRS = [43, 14, 253, 186]
1010
TABLE_WIDTH = 80
1111

1212

13-
class TestSimulatorDisplay(unittest.TestCase):
14-
def apply_cache_statuses_to_refs(self, cache_statuses, refs):
15-
for cache_status, ref in zip(cache_statuses, refs):
16-
ref.cache_status = cache_status
17-
18-
def test_display_addr_refs(self):
19-
"""should display table of address references"""
20-
sim = Simulator()
21-
refs = sim.get_addr_refs(
22-
word_addrs=WORD_ADDRS,
23-
num_addr_bits=8,
24-
num_tag_bits=5,
25-
num_index_bits=2,
26-
num_offset_bits=1,
27-
)
28-
self.apply_cache_statuses_to_refs(["miss", "miss", "HIT", "miss"], refs)
29-
out = io.StringIO()
30-
with contextlib.redirect_stdout(out):
31-
sim.display_addr_refs(refs, table_width=TABLE_WIDTH)
32-
table_output = out.getvalue()
33-
num_cols = 6
34-
col_width = TABLE_WIDTH // num_cols
35-
self.assertRegex(
36-
table_output,
37-
r"{}\s*{}\s*{}\s*{}\s*{}\s*{}\n{}".format(
38-
"WordAddr".rjust(col_width),
39-
"BinAddr".rjust(col_width),
40-
"Tag".rjust(col_width),
41-
"Index".rjust(col_width),
42-
"Offset".rjust(col_width),
43-
"Hit/Miss".rjust(col_width),
44-
("-" * TABLE_WIDTH),
45-
),
46-
)
47-
self.assertRegex(
48-
table_output,
49-
r"{}\s*{}\s*{}\s*{}\s*{}\s*{}".format(
50-
"253".rjust(col_width),
51-
"1111 1101".rjust(col_width),
52-
"11111".rjust(col_width),
53-
"10".rjust(col_width),
54-
"1".rjust(col_width),
55-
"HIT".rjust(col_width),
56-
),
57-
)
13+
def apply_cache_statuses_to_refs(cache_statuses, refs):
14+
for cache_status, ref in zip(cache_statuses, refs):
15+
ref.cache_status = cache_status
5816

59-
def test_display_addr_refs_no_tag(self):
60-
"""should display n/a for tag when there are no tag bits"""
61-
sim = Simulator()
62-
refs = sim.get_addr_refs(
63-
word_addrs=WORD_ADDRS,
64-
num_addr_bits=2,
65-
num_tag_bits=0,
66-
num_index_bits=1,
67-
num_offset_bits=1,
68-
)
69-
self.apply_cache_statuses_to_refs(["miss", "miss", "miss", "miss"], refs)
70-
out = io.StringIO()
71-
with contextlib.redirect_stdout(out):
72-
sim.display_addr_refs(refs, table_width=TABLE_WIDTH)
73-
table_output = out.getvalue()
74-
self.assertRegex(
75-
table_output, r"\s*{}\s*{}\s*{}".format(r"\d\d", r"n/a", r"\d")
76-
)
7717

78-
def test_display_addr_refs_no_index(self):
79-
"""should display n/a for index when there are no index bits"""
80-
sim = Simulator()
81-
refs = sim.get_addr_refs(
82-
word_addrs=WORD_ADDRS,
83-
num_addr_bits=8,
84-
num_tag_bits=7,
85-
num_index_bits=0,
86-
num_offset_bits=1,
87-
)
88-
self.apply_cache_statuses_to_refs(["miss", "miss", "miss", "miss"], refs)
89-
out = io.StringIO()
90-
with contextlib.redirect_stdout(out):
91-
sim.display_addr_refs(refs, table_width=TABLE_WIDTH)
92-
table_output = out.getvalue()
93-
self.assertRegex(table_output, r"\s*{}\s*{}\s*{}".format(r"n/a", r"\d", "miss"))
94-
95-
def test_display_addr_refs_no_offset(self):
96-
"""should display n/a for offset when there are no offset bits"""
97-
sim = Simulator()
98-
refs = sim.get_addr_refs(
99-
word_addrs=WORD_ADDRS,
100-
num_addr_bits=8,
101-
num_tag_bits=4,
102-
num_index_bits=4,
103-
num_offset_bits=0,
104-
)
105-
self.apply_cache_statuses_to_refs(["miss"] * 12, refs)
106-
out = io.StringIO()
107-
with contextlib.redirect_stdout(out):
108-
sim.display_addr_refs(refs, table_width=TABLE_WIDTH)
109-
table_output = out.getvalue()
110-
self.assertRegex(
111-
table_output, r"\s*{}\s*{}\s*{}".format(r"\d\d", r"n/a", "miss")
112-
)
18+
def test_display_addr_refs():
19+
"""should display table of address references"""
20+
sim = Simulator()
21+
refs = sim.get_addr_refs(
22+
word_addrs=WORD_ADDRS,
23+
num_addr_bits=8,
24+
num_tag_bits=5,
25+
num_index_bits=2,
26+
num_offset_bits=1,
27+
)
28+
apply_cache_statuses_to_refs(["miss", "miss", "HIT", "miss"], refs)
29+
out = io.StringIO()
30+
with contextlib.redirect_stdout(out):
31+
sim.display_addr_refs(refs, table_width=TABLE_WIDTH)
32+
table_output = out.getvalue()
33+
num_cols = 6
34+
col_width = TABLE_WIDTH // num_cols
35+
assert re.search(
36+
r"{}\s*{}\s*{}\s*{}\s*{}\s*{}\n{}".format(
37+
"WordAddr".rjust(col_width),
38+
"BinAddr".rjust(col_width),
39+
"Tag".rjust(col_width),
40+
"Index".rjust(col_width),
41+
"Offset".rjust(col_width),
42+
"Hit/Miss".rjust(col_width),
43+
("-" * TABLE_WIDTH),
44+
),
45+
table_output,
46+
)
47+
assert re.search(
48+
r"{}\s*{}\s*{}\s*{}\s*{}\s*{}".format(
49+
"253".rjust(col_width),
50+
"1111 1101".rjust(col_width),
51+
"11111".rjust(col_width),
52+
"10".rjust(col_width),
53+
"1".rjust(col_width),
54+
"HIT".rjust(col_width),
55+
),
56+
table_output,
57+
)
11358

114-
def test_display_cache(self):
115-
"""should display table for direct-mapped/set associative cache"""
116-
sim = Simulator()
117-
out = io.StringIO()
118-
with contextlib.redirect_stdout(out):
119-
sim.display_cache(
120-
{
121-
"000": [{"tag": "0101", "data": [88, 89]}],
122-
"001": [
123-
{"tag": "0000", "data": [2, 3]},
124-
{"tag": "0010", "data": [42, 43]},
125-
],
126-
},
127-
table_width=TABLE_WIDTH,
128-
)
129-
table_output = out.getvalue()
130-
num_cols = 2
131-
col_width = TABLE_WIDTH // num_cols
132-
self.assertRegex(
133-
table_output,
134-
"{}\n{}".format("Cache".center(TABLE_WIDTH), ("-" * TABLE_WIDTH)),
135-
)
136-
self.assertEqual(table_output.count("-"), TABLE_WIDTH * 2)
137-
self.assertRegex(
138-
table_output,
139-
r"{}{}".format("000".center(col_width), "001".center(col_width)),
140-
)
141-
self.assertRegex(
142-
table_output,
143-
r"{}{}".format("88,89".center(col_width), "2,3 42,43".center(col_width)),
59+
60+
def test_display_addr_refs_no_tag():
61+
"""should display n/a for tag when there are no tag bits"""
62+
sim = Simulator()
63+
refs = sim.get_addr_refs(
64+
word_addrs=WORD_ADDRS,
65+
num_addr_bits=2,
66+
num_tag_bits=0,
67+
num_index_bits=1,
68+
num_offset_bits=1,
69+
)
70+
apply_cache_statuses_to_refs(["miss", "miss", "miss", "miss"], refs)
71+
out = io.StringIO()
72+
with contextlib.redirect_stdout(out):
73+
sim.display_addr_refs(refs, table_width=TABLE_WIDTH)
74+
table_output = out.getvalue()
75+
assert re.search(r"\s*{}\s*{}\s*{}".format(r"\d\d", r"n/a", r"\d"), table_output)
76+
77+
78+
def test_display_addr_refs_no_index():
79+
"""should display n/a for index when there are no index bits"""
80+
sim = Simulator()
81+
refs = sim.get_addr_refs(
82+
word_addrs=WORD_ADDRS,
83+
num_addr_bits=8,
84+
num_tag_bits=7,
85+
num_index_bits=0,
86+
num_offset_bits=1,
87+
)
88+
apply_cache_statuses_to_refs(["miss", "miss", "miss", "miss"], refs)
89+
out = io.StringIO()
90+
with contextlib.redirect_stdout(out):
91+
sim.display_addr_refs(refs, table_width=TABLE_WIDTH)
92+
table_output = out.getvalue()
93+
assert re.search(r"\s*{}\s*{}\s*{}".format(r"n/a", r"\d", "miss"), table_output)
94+
95+
96+
def test_display_addr_refs_no_offset():
97+
"""should display n/a for offset when there are no offset bits"""
98+
sim = Simulator()
99+
refs = sim.get_addr_refs(
100+
word_addrs=WORD_ADDRS,
101+
num_addr_bits=8,
102+
num_tag_bits=4,
103+
num_index_bits=4,
104+
num_offset_bits=0,
105+
)
106+
apply_cache_statuses_to_refs(["miss"] * 12, refs)
107+
out = io.StringIO()
108+
with contextlib.redirect_stdout(out):
109+
sim.display_addr_refs(refs, table_width=TABLE_WIDTH)
110+
table_output = out.getvalue()
111+
assert re.search(r"\s*{}\s*{}\s*{}".format(r"\d\d", r"n/a", "miss"), table_output)
112+
113+
114+
def test_display_cache():
115+
"""should display table for direct-mapped/set associative cache"""
116+
sim = Simulator()
117+
out = io.StringIO()
118+
with contextlib.redirect_stdout(out):
119+
sim.display_cache(
120+
{
121+
"000": [{"tag": "0101", "data": [88, 89]}],
122+
"001": [
123+
{"tag": "0000", "data": [2, 3]},
124+
{"tag": "0010", "data": [42, 43]},
125+
],
126+
},
127+
table_width=TABLE_WIDTH,
144128
)
129+
table_output = out.getvalue()
130+
num_cols = 2
131+
col_width = TABLE_WIDTH // num_cols
132+
assert re.search(
133+
"{}\n{}".format("Cache".center(TABLE_WIDTH), ("-" * TABLE_WIDTH)),
134+
table_output,
135+
)
136+
assert table_output.count("-") == TABLE_WIDTH * 2
137+
assert re.search(
138+
r"{}{}".format("000".center(col_width), "001".center(col_width)),
139+
table_output,
140+
)
141+
assert re.search(
142+
r"{}{}".format("88,89".center(col_width), "2,3 42,43".center(col_width)),
143+
table_output,
144+
)
145+
145146

146-
def test_display_cache_fully_assoc(self):
147-
"""should correctly display table for fully associative cache"""
148-
sim = Simulator()
149-
out = io.StringIO()
150-
with contextlib.redirect_stdout(out):
151-
sim.display_cache(
152-
{
153-
"0": [
154-
{"tag": "0000001", "data": [2, 3]},
155-
{"tag": "1111110", "data": [252, 253]},
156-
]
157-
},
158-
table_width=TABLE_WIDTH,
159-
)
160-
table_output = out.getvalue()
161-
self.assertRegex(
162-
table_output,
163-
"{}\n{}".format("Cache".center(TABLE_WIDTH), ("-" * TABLE_WIDTH)),
147+
def test_display_cache_fully_assoc():
148+
"""should correctly display table for fully associative cache"""
149+
sim = Simulator()
150+
out = io.StringIO()
151+
with contextlib.redirect_stdout(out):
152+
sim.display_cache(
153+
{
154+
"0": [
155+
{"tag": "0000001", "data": [2, 3]},
156+
{"tag": "1111110", "data": [252, 253]},
157+
]
158+
},
159+
table_width=TABLE_WIDTH,
164160
)
165-
self.assertEqual(table_output.count("-"), TABLE_WIDTH)
166-
self.assertRegex(table_output, "2,3 252,253".center(TABLE_WIDTH))
161+
table_output = out.getvalue()
162+
assert re.search(
163+
"{}\n{}".format("Cache".center(TABLE_WIDTH), ("-" * TABLE_WIDTH)),
164+
table_output,
165+
)
166+
assert table_output.count("-") == TABLE_WIDTH
167+
assert re.search("2,3 252,253".center(TABLE_WIDTH), table_output)

0 commit comments

Comments
 (0)