Skip to content

Commit 9dfacc0

Browse files
- Whole table match scenario.
- Nonempty table match scenario. - Skip testing on files named `README.md`.
1 parent 01b7565 commit 9dfacc0

File tree

3 files changed

+105
-4
lines changed

3 files changed

+105
-4
lines changed

docs/walkthroughs/README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
2+
# `stackql` walkthroughs
3+
4+
All markdown documents hereunder, execept those named `README.md`,
5+
are **provably working** examples of `stackql` in action.
6+
These materials serve as useful examples and reference materials for
7+
using `stackql`. If you have some use case that you would like to see added here; please let us know!
8+
9+
10+
All walkthrough files are testable with CI, leveraging annotations (eg: code block info strings)
11+
in order to setup, run, verify and tear down testing scenarios. The tests *can* be run:
12+
13+
- Locally, on your own machine. Thats the whole idea; please mix and match and let us know any ideas thast occur.
14+
- Directly from CI. Reports are generated and archived.
15+
- From test harnesses, such as robot framework. This has not yet been implemented.
16+
17+
18+
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
2+
## Setup
3+
4+
First, create a google service account key using the GCP Console, per [the GCP documentation](https://cloud.google.com/iam/docs/keys-create-delete). Grant the service account at least `Viewer` role equivalent privileges, per [the GCP dumentation](https://cloud.google.com/iam/docs/create-service-agents#grant-roles).
5+
6+
Then, do this in bash:
7+
8+
```bash setup stackql-shell credentials-path=cicd/keys/testing/google-ro-credentials.json app-root-path=./test/tmp/.get-google-accel.stackql
9+
10+
export GOOGLE_CREDENTIALS="$(cat <credentials-path>)";
11+
12+
stackql shell --approot=<app-root-path>
13+
```
14+
15+
## Method
16+
17+
Do this in the `stackql` shell, replacing `<project>` with your GCP project name:
18+
19+
```sql stackql-shell input required project=ryuki-it-sandbox-01 region=australia-southeast1-a
20+
21+
registry pull google;
22+
23+
select
24+
name,
25+
kind
26+
FROM google.compute.accelerator_types
27+
WHERE
28+
project = '<project>'
29+
AND zone = '<region>'
30+
ORDER BY
31+
name desc
32+
;
33+
34+
```
35+
36+
## Result
37+
38+
39+
You will see something very much like this included in the output, presuming you have one VM (if you have zero, only the headers should appper, more VMs means more rows):
40+
41+
```sql expectation stdout-contains-all
42+
|---------------------|-------------------------|
43+
| name | kind |
44+
|---------------------|-------------------------|
45+
| nvidia-tesla-t4-vws | compute#acceleratorType |
46+
|---------------------|-------------------------|
47+
| nvidia-tesla-t4 | compute#acceleratorType |
48+
|---------------------|-------------------------|
49+
| nvidia-tesla-p4-vws | compute#acceleratorType |
50+
|---------------------|-------------------------|
51+
| nvidia-tesla-p4 | compute#acceleratorType |
52+
|---------------------|-------------------------|
53+
```
54+
55+
<!--- EXPECTATION
56+
google\ provider,\ version\ 'v24.11.00274'\ successfully\ installed
57+
goodbye
58+
-->
59+
60+
<x-expectation style="display: none;">
61+
<stdout-contains-nonempty-table></stdout-contains-nonempty-table>
62+
</x-expectation>
63+
64+
## Cleanup
65+
66+
```bash teardown best-effort app-root-path=./test/tmp/.get-google-accel.stackql
67+
68+
rm -rf <app-root-path>
69+
70+
```

test/python/markdown_testing/markdown_testing.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
- Support sequential markdown code block execution, leveraging [info strings](https://spec.commonmark.org/0.30/#info-string).
1616
"""
1717

18+
def eprint(*args, **kwargs):
19+
print(*args, file=sys.stderr, **kwargs)
20+
1821
class ASTNode(object):
1922

2023
_STACKQL_SHELL_INVOCATION: str = 'stackql-shell'
@@ -120,6 +123,7 @@ def parse_markdown_file(self, file_path: str, lang=None) -> MdAST:
120123
class Expectation(object):
121124

122125
_STDOUT_TABLE_CONTAINS_DATA: str = 'stdout-table-contains-data'
126+
_STDOUT_CONTAINS_ALL: str = 'stdout-contains-all'
123127

124128
def __init__(self, node: ASTNode):
125129
self._node: ASTNode = node
@@ -142,7 +146,11 @@ def _contains_nonempty_table(self, s: str) -> bool:
142146

143147
def passes_stdout(self, actual_stdout: str) -> bool:
144148
if self._node.has_annotation(self._STDOUT_TABLE_CONTAINS_DATA):
149+
eprint(f'running expectation check: {self._STDOUT_TABLE_CONTAINS_DATA}')
145150
return self._contains_nonempty_table(actual_stdout)
151+
if self._node.has_annotation(self._STDOUT_CONTAINS_ALL):
152+
eprint(f'running expectation check: {self._STDOUT_CONTAINS_ALL}')
153+
return self._node.get_text() in actual_stdout
146154
return True
147155

148156
def passes_stderr(self, actual_stderr: str) -> bool:
@@ -240,7 +248,6 @@ def orchestrate(self, file_path: str) -> WorkloadDTO:
240248

241249
class WalkthroughResult:
242250

243-
244251
def __init__(self, stdout_str :str, stderr_str :str, rc :int) -> None:
245252
self.stdout :str = stdout_str
246253
self.stderr :str = stderr_str
@@ -251,7 +258,7 @@ class SimpleRunner(object):
251258
def __init__(self, workload: WorkloadDTO):
252259
self._workload = workload
253260

254-
def run(self) -> Tuple[bytes, bytes]:
261+
def run(self) -> WalkthroughResult:
255262
bash_path = shutil.which('bash')
256263
pr: subprocess.Popen = subprocess.Popen(
257264
self._workload.get_setup(),
@@ -282,13 +289,16 @@ def __init__(self):
282289
md_parser = MdParser()
283290
self._orchestrator: MdOrchestrator = MdOrchestrator(md_parser)
284291

285-
def run_all(self, walkthrough_inodes: List[str], recursive=True) -> List[WalkthroughResult]:
292+
def run_all(self, walkthrough_inodes: List[str], recursive=True, skip_readme=True) -> List[WalkthroughResult]:
286293
results: List[WalkthroughResult] = []
287294
for inode_path in walkthrough_inodes:
288295
is_dir = os.path.isdir(inode_path)
289296
if is_dir:
290297
for root, dirs, files in os.walk(inode_path):
291298
for file in files:
299+
if skip_readme and file == 'README.md':
300+
eprint(f'Skipping README.md')
301+
continue
292302
file_path = os.path.join(root, file)
293303
print(f'File path: {file_path}')
294304
workload: WorkloadDTO = self._orchestrator.orchestrate(file_path)
@@ -302,6 +312,9 @@ def run_all(self, walkthrough_inodes: List[str], recursive=True) -> List[Walkthr
302312
continue
303313
is_file = os.path.isfile(inode_path)
304314
if is_file:
315+
if skip_readme and file == 'README.md':
316+
eprint(f'Skipping README.md')
317+
continue
305318
file_path = inode_path
306319
workload: WorkloadDTO = self._orchestrator.orchestrate(file_path)
307320
e2e: SimpleRunner = SimpleRunner(workload)
@@ -311,7 +324,7 @@ def run_all(self, walkthrough_inodes: List[str], recursive=True) -> List[Walkthr
311324
raise FileNotFoundError(f'Path not tractable: {inode_path}')
312325
return results
313326

314-
def main():
327+
def main():
315328
runner: AllWalkthroughsRunner = AllWalkthroughsRunner()
316329
results: List[WalkthroughResult] = runner.run_all([os.path.join(_REPOSITORY_ROOT_PATH, 'docs', 'walkthroughs')])
317330
for result in results:

0 commit comments

Comments
 (0)