mirror of
https://github.com/scito/extract_otp_secret_keys.git
synced 2025-12-06 14:54:57 +01:00
add output tests
This commit is contained in:
parent
eac342c0cc
commit
9d08ebaa38
5 changed files with 255 additions and 7 deletions
|
|
@ -84,24 +84,23 @@ devbox shell
|
||||||
|
|
||||||
### PyTest
|
### PyTest
|
||||||
|
|
||||||
There are basic pytests, see `test_extract_otp_secret_keys_pytest.py`.
|
There are basic [pytest](https://pytest.org)s, see `test_extract_otp_secret_keys_pytest.py`.
|
||||||
|
|
||||||
Run tests:
|
Run tests:
|
||||||
|
|
||||||
```
|
```
|
||||||
pytest unittest
|
pytest
|
||||||
```
|
```
|
||||||
or
|
or
|
||||||
|
|
||||||
```
|
```
|
||||||
python -m pytest
|
python -m pytest
|
||||||
```
|
```
|
||||||
|
|
||||||
### unittest
|
### unittest
|
||||||
|
|
||||||
There are basic unit tests, see `test_extract_otp_secret_keys_unittest.py`.
|
There are basic [unittest](https://docs.python.org/3.10/library/unittest.html)s, see `test_extract_otp_secret_keys_unittest.py`.
|
||||||
|
|
||||||
Run unit tests:
|
Run tests:
|
||||||
|
|
||||||
```
|
```
|
||||||
python -m unittest
|
python -m unittest
|
||||||
|
|
|
||||||
106
test/printqr_output.txt
Normal file
106
test/printqr_output.txt
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
Name: pi@raspberrypi
|
||||||
|
Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY
|
||||||
|
Issuer: raspberrypi
|
||||||
|
Type: OTP_TOTP
|
||||||
|
|
||||||
|
|
||||||
|
█▀▀▀▀▀█ ▄▀▄▄█ █▀ ▀▀▀▀▀█ ▄▄ █▀▀▀▀▀█
|
||||||
|
█ ███ █ ███▀ ▀█ █▄ ▀ ▀▄▀█▄▄ █ █ ███ █
|
||||||
|
█ ▀▀▀ █ ██▄▄ ██ ▀█▀█▄▄▀▄ ▄▄█ █ ▀▀▀ █
|
||||||
|
▀▀▀▀▀▀▀ █ █ █▄▀ █ ▀▄▀▄█ █ ▀ █ ▀▀▀▀▀▀▀
|
||||||
|
█▄█▀▀█▀ ▄▀▀ ▄▀██▄▀ ▄█▄█▄ ▄▄ ██▀▀█▄
|
||||||
|
▀ █▀▀▀ ██▀█ ▄▀▀▄ ██ ▄▀▄█ █ ▄▄▀█
|
||||||
|
▄█▀█ ▄▀█▄▄ ▄▀▄▄▀ ▄█▄█▄ ▀ ▀ ▀▄▀▀█
|
||||||
|
▀▄ ▄▄▄▀▄█▄██▀▄██▀ █▄█▄ ▄▄▀▄█ ▄ █▀ ▀
|
||||||
|
▄ ▄█ ▀▀▄▄ ▄▄▀█▄█▀▀▄██▄▀▄▀▀ █▀█ █▄███
|
||||||
|
▀▀▄▀ ▀ ▀▄▀▀█ █▀▀█ █▄ █▄██ ▀█▀▀█▀
|
||||||
|
▀█▄██▀▀█ ▄▀█▀███▄▄▀▄█▄ ▀▄▀██▀▀▀▄ ▀▄
|
||||||
|
█▄█ ▀ ▀▀▀▄▄▄ ▀ ▀█▄ ▄▀▀█▄██ ▄ ▀▄
|
||||||
|
█▀ ▀ ▀▄ █▀▀█▀▀█▄ ██▄▄█▄ ▀▀▀▄█▀▀▀ ▀ ▀
|
||||||
|
█ █▀▄▄▀█▀█▀▀▀ ▀ ▄ ▄ ▄ ▄▄ ▀▀▀▀█▄▄▄ █▀
|
||||||
|
▀ ▀▀ ▀▀ ▄ █▀▀▀ █ ▄▄▄█▄▀█▄▀█▀▀▀█ ▀▀▀
|
||||||
|
█▀▀▀▀▀█ ▄▀█▀█ ███▄ ▄▄▄█ ▄ █ ▀ █ ▄
|
||||||
|
█ ███ █ █▄█▄▄▀█▄▀ ▄▄▄ █▄ ▀█▀███▀█ ▀▀
|
||||||
|
█ ▀▀▀ █ ▀█▄▄▄█▀█▀ ▄ █▄▄▄ █ ▀ ██ █
|
||||||
|
▀▀▀▀▀▀▀ ▀ ▀ ▀▀▀▀▀▀ ▀ ▀ ▀▀ ▀ ▀▀ ▀ ▀▀
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Name: pi@raspberrypi
|
||||||
|
Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY
|
||||||
|
Type: OTP_TOTP
|
||||||
|
|
||||||
|
|
||||||
|
█▀▀▀▀▀█ ▀▀██ █▄▀█ ▀▄▄▀█▀▄ █▀▀▀▀▀█
|
||||||
|
█ ███ █ ▄ ▀▀▀ ▀▀█▀█▀▄ ▄█▀ █ ███ █
|
||||||
|
█ ▀▀▀ █ █▀▄▄▄█▄▄▀ ▄ ▄ ▀▄▄ █ ▀▀▀ █
|
||||||
|
▀▀▀▀▀▀▀ █ █▄▀ ▀ ▀▄█ ▀▄█ █ ▀▀▀▀▀▀▀
|
||||||
|
▀▄▄▄█▄▀██▄█▀█ ▄███ █ █ ▀▀▀▀█▄▄▀
|
||||||
|
▄▀ ▀ █ █▀█▀▀█▀ ▄█▀██▀█▀▀ █▄
|
||||||
|
█▀█ ▄▀▀▀ ███▄█▄ ▀ █▀▄█▀▀█▀▀▀█▄▀▀
|
||||||
|
▀▄▀▄▄ ▀▄▄ ▀▀▄█▀██▄▄ █▄ ▄ █▀█ █▄
|
||||||
|
▀██▄█▄▀█ ▄▄ ▀▀▄▄█▀ ▀▄▀█▄▀█▀▄▀ ▄
|
||||||
|
▀▄▄▀▄▀▀▀▄ █ ▀█▀█▄▄ ▄█ █▄ ▀█▀ █▄
|
||||||
|
▄█ ▄ ▀ ▀ ▄ ▀█ ▄ ▀▄█ ▀▄▄█ ▄█▀ ▄▄
|
||||||
|
▄█▀▄▀▀ ██ ▄ ▀ █ █▀██ ███ █ ▀█▄
|
||||||
|
▀▀▀ ▀▀ ▄██▀█▀███▀▄ ▄▀▀██▀▀▀█▀▄ ▀
|
||||||
|
█▀▀▀▀▀█ ▀█▀▄██▀█ ▀█ █ ▄ █ ▀ █ ▄
|
||||||
|
█ ███ █ ▀█▄▄█▀▀▄ ▀▀▄▄ ▄▀████▀▄█
|
||||||
|
█ ▀▀▀ █ ▄ █ █▀▀▀▄ ▄█▀▄▀ ▀ █▀▀
|
||||||
|
▀▀▀▀▀▀▀ ▀ ▀ ▀ ▀▀ ▀ ▀▀ ▀▀ ▀▀ ▀
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Name: pi@raspberrypi
|
||||||
|
Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY
|
||||||
|
Type: OTP_TOTP
|
||||||
|
|
||||||
|
|
||||||
|
█▀▀▀▀▀█ ▀▀██ █▄▀█ ▀▄▄▀█▀▄ █▀▀▀▀▀█
|
||||||
|
█ ███ █ ▄ ▀▀▀ ▀▀█▀█▀▄ ▄█▀ █ ███ █
|
||||||
|
█ ▀▀▀ █ █▀▄▄▄█▄▄▀ ▄ ▄ ▀▄▄ █ ▀▀▀ █
|
||||||
|
▀▀▀▀▀▀▀ █ █▄▀ ▀ ▀▄█ ▀▄█ █ ▀▀▀▀▀▀▀
|
||||||
|
▀▄▄▄█▄▀██▄█▀█ ▄███ █ █ ▀▀▀▀█▄▄▀
|
||||||
|
▄▀ ▀ █ █▀█▀▀█▀ ▄█▀██▀█▀▀ █▄
|
||||||
|
█▀█ ▄▀▀▀ ███▄█▄ ▀ █▀▄█▀▀█▀▀▀█▄▀▀
|
||||||
|
▀▄▀▄▄ ▀▄▄ ▀▀▄█▀██▄▄ █▄ ▄ █▀█ █▄
|
||||||
|
▀██▄█▄▀█ ▄▄ ▀▀▄▄█▀ ▀▄▀█▄▀█▀▄▀ ▄
|
||||||
|
▀▄▄▀▄▀▀▀▄ █ ▀█▀█▄▄ ▄█ █▄ ▀█▀ █▄
|
||||||
|
▄█ ▄ ▀ ▀ ▄ ▀█ ▄ ▀▄█ ▀▄▄█ ▄█▀ ▄▄
|
||||||
|
▄█▀▄▀▀ ██ ▄ ▀ █ █▀██ ███ █ ▀█▄
|
||||||
|
▀▀▀ ▀▀ ▄██▀█▀███▀▄ ▄▀▀██▀▀▀█▀▄ ▀
|
||||||
|
█▀▀▀▀▀█ ▀█▀▄██▀█ ▀█ █ ▄ █ ▀ █ ▄
|
||||||
|
█ ███ █ ▀█▄▄█▀▀▄ ▀▀▄▄ ▄▀████▀▄█
|
||||||
|
█ ▀▀▀ █ ▄ █ █▀▀▀▄ ▄█▀▄▀ ▀ █▀▀
|
||||||
|
▀▀▀▀▀▀▀ ▀ ▀ ▀ ▀▀ ▀ ▀▀ ▀▀ ▀▀ ▀
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Name: pi@raspberrypi
|
||||||
|
Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY
|
||||||
|
Issuer: raspberrypi
|
||||||
|
Type: OTP_TOTP
|
||||||
|
|
||||||
|
|
||||||
|
█▀▀▀▀▀█ ▄▀▄▄█ █▀ ▀▀▀▀▀█ ▄▄ █▀▀▀▀▀█
|
||||||
|
█ ███ █ ███▀ ▀█ █▄ ▀ ▀▄▀█▄▄ █ █ ███ █
|
||||||
|
█ ▀▀▀ █ ██▄▄ ██ ▀█▀█▄▄▀▄ ▄▄█ █ ▀▀▀ █
|
||||||
|
▀▀▀▀▀▀▀ █ █ █▄▀ █ ▀▄▀▄█ █ ▀ █ ▀▀▀▀▀▀▀
|
||||||
|
█▄█▀▀█▀ ▄▀▀ ▄▀██▄▀ ▄█▄█▄ ▄▄ ██▀▀█▄
|
||||||
|
▀ █▀▀▀ ██▀█ ▄▀▀▄ ██ ▄▀▄█ █ ▄▄▀█
|
||||||
|
▄█▀█ ▄▀█▄▄ ▄▀▄▄▀ ▄█▄█▄ ▀ ▀ ▀▄▀▀█
|
||||||
|
▀▄ ▄▄▄▀▄█▄██▀▄██▀ █▄█▄ ▄▄▀▄█ ▄ █▀ ▀
|
||||||
|
▄ ▄█ ▀▀▄▄ ▄▄▀█▄█▀▀▄██▄▀▄▀▀ █▀█ █▄███
|
||||||
|
▀▀▄▀ ▀ ▀▄▀▀█ █▀▀█ █▄ █▄██ ▀█▀▀█▀
|
||||||
|
▀█▄██▀▀█ ▄▀█▀███▄▄▀▄█▄ ▀▄▀██▀▀▀▄ ▀▄
|
||||||
|
█▄█ ▀ ▀▀▀▄▄▄ ▀ ▀█▄ ▄▀▀█▄██ ▄ ▀▄
|
||||||
|
█▀ ▀ ▀▄ █▀▀█▀▀█▄ ██▄▄█▄ ▀▀▀▄█▀▀▀ ▀ ▀
|
||||||
|
█ █▀▄▄▀█▀█▀▀▀ ▀ ▄ ▄ ▄ ▄▄ ▀▀▀▀█▄▄▄ █▀
|
||||||
|
▀ ▀▀ ▀▀ ▄ █▀▀▀ █ ▄▄▄█▄▀█▄▀█▀▀▀█ ▀▀▀
|
||||||
|
█▀▀▀▀▀█ ▄▀█▀█ ███▄ ▄▄▄█ ▄ █ ▀ █ ▄
|
||||||
|
█ ███ █ █▄█▄▄▀█▄▀ ▄▄▄ █▄ ▀█▀███▀█ ▀▀
|
||||||
|
█ ▀▀▀ █ ▀█▄▄▄█▀█▀ ▄ █▄▄▄ █ ▀ ██ █
|
||||||
|
▀▀▀▀▀▀▀ ▀ ▀ ▀▀▀▀▀▀ ▀ ▀ ▀▀ ▀ ▀▀ ▀ ▀▀
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from utils import read_csv, read_json, remove_file
|
from utils import read_csv, read_json, remove_file, read_file_to_str
|
||||||
|
|
||||||
import extract_otp_secret_keys
|
import extract_otp_secret_keys
|
||||||
|
|
||||||
|
|
@ -47,6 +47,7 @@ def test_extract_json():
|
||||||
# Act
|
# Act
|
||||||
extract_otp_secret_keys.main(['-q', '-j', 'test_example_output.json', 'example_export.txt'])
|
extract_otp_secret_keys.main(['-q', '-j', 'test_example_output.json', 'example_export.txt'])
|
||||||
|
|
||||||
|
# Assert
|
||||||
expected_json = read_json('example_output.json')
|
expected_json = read_json('example_output.json')
|
||||||
actual_json = read_json('test_example_output.json')
|
actual_json = read_json('test_example_output.json')
|
||||||
|
|
||||||
|
|
@ -56,6 +57,50 @@ def test_extract_json():
|
||||||
cleanup()
|
cleanup()
|
||||||
|
|
||||||
|
|
||||||
|
def test_extract_stdout(capsys):
|
||||||
|
# Act
|
||||||
|
extract_otp_secret_keys.main(['example_export.txt'])
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
captured = capsys.readouterr()
|
||||||
|
|
||||||
|
expected_stdout = '''Name: pi@raspberrypi
|
||||||
|
Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY
|
||||||
|
Issuer: raspberrypi
|
||||||
|
Type: OTP_TOTP
|
||||||
|
|
||||||
|
Name: pi@raspberrypi
|
||||||
|
Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY
|
||||||
|
Type: OTP_TOTP
|
||||||
|
|
||||||
|
Name: pi@raspberrypi
|
||||||
|
Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY
|
||||||
|
Type: OTP_TOTP
|
||||||
|
|
||||||
|
Name: pi@raspberrypi
|
||||||
|
Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY
|
||||||
|
Issuer: raspberrypi
|
||||||
|
Type: OTP_TOTP
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
assert captured.out == expected_stdout
|
||||||
|
assert captured.err == ''
|
||||||
|
|
||||||
|
|
||||||
|
def test_extract_printqr(capsys):
|
||||||
|
# Act
|
||||||
|
extract_otp_secret_keys.main(['-p', 'example_export.txt'])
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
captured = capsys.readouterr()
|
||||||
|
|
||||||
|
expected_stdout = read_file_to_str('test/printqr_output.txt')
|
||||||
|
|
||||||
|
assert captured.out == expected_stdout
|
||||||
|
assert captured.err == ''
|
||||||
|
|
||||||
|
|
||||||
def cleanup():
|
def cleanup():
|
||||||
remove_file('test_example_output.csv')
|
remove_file('test_example_output.csv')
|
||||||
remove_file('test_example_output.json')
|
remove_file('test_example_output.json')
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,9 @@
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
from utils import read_csv, read_json, remove_file
|
import io
|
||||||
|
from contextlib import redirect_stdout
|
||||||
|
from utils import read_csv, read_json, remove_file, Capturing, read_file_to_str
|
||||||
|
|
||||||
import extract_otp_secret_keys
|
import extract_otp_secret_keys
|
||||||
|
|
||||||
|
|
@ -42,6 +44,70 @@ class TestExtract(unittest.TestCase):
|
||||||
|
|
||||||
self.assertEqual(actual_json, expected_json)
|
self.assertEqual(actual_json, expected_json)
|
||||||
|
|
||||||
|
def test_extract_stdout_1(self):
|
||||||
|
with Capturing() as output:
|
||||||
|
extract_otp_secret_keys.main(['example_export.txt'])
|
||||||
|
|
||||||
|
expected_output = [
|
||||||
|
'Name: pi@raspberrypi',
|
||||||
|
'Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY',
|
||||||
|
'Issuer: raspberrypi',
|
||||||
|
'Type: OTP_TOTP',
|
||||||
|
'',
|
||||||
|
'Name: pi@raspberrypi',
|
||||||
|
'Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY',
|
||||||
|
'Type: OTP_TOTP',
|
||||||
|
'',
|
||||||
|
'Name: pi@raspberrypi',
|
||||||
|
'Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY',
|
||||||
|
'Type: OTP_TOTP',
|
||||||
|
'',
|
||||||
|
'Name: pi@raspberrypi',
|
||||||
|
'Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY',
|
||||||
|
'Issuer: raspberrypi',
|
||||||
|
'Type: OTP_TOTP',
|
||||||
|
''
|
||||||
|
]
|
||||||
|
self.assertEqual(output, expected_output)
|
||||||
|
|
||||||
|
# Ref for capturing https://stackoverflow.com/a/40984270
|
||||||
|
def test_extract_stdout_2(self):
|
||||||
|
out = io.StringIO()
|
||||||
|
with redirect_stdout(out):
|
||||||
|
extract_otp_secret_keys.main(['example_export.txt'])
|
||||||
|
actual_output = out.getvalue()
|
||||||
|
|
||||||
|
expected_output = '''Name: pi@raspberrypi
|
||||||
|
Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY
|
||||||
|
Issuer: raspberrypi
|
||||||
|
Type: OTP_TOTP
|
||||||
|
|
||||||
|
Name: pi@raspberrypi
|
||||||
|
Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY
|
||||||
|
Type: OTP_TOTP
|
||||||
|
|
||||||
|
Name: pi@raspberrypi
|
||||||
|
Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY
|
||||||
|
Type: OTP_TOTP
|
||||||
|
|
||||||
|
Name: pi@raspberrypi
|
||||||
|
Secret: 7KSQL2JTUDIS5EF65KLMRQIIGY
|
||||||
|
Issuer: raspberrypi
|
||||||
|
Type: OTP_TOTP
|
||||||
|
|
||||||
|
'''
|
||||||
|
self.assertEqual(actual_output, expected_output)
|
||||||
|
|
||||||
|
def test_extract_printqr(self):
|
||||||
|
out = io.StringIO()
|
||||||
|
with redirect_stdout(out):
|
||||||
|
extract_otp_secret_keys.main(['-p', 'example_export.txt'])
|
||||||
|
actual_output = out.getvalue()
|
||||||
|
|
||||||
|
expected_output = read_file_to_str('test/printqr_output.txt')
|
||||||
|
|
||||||
|
self.assertEqual(actual_output, expected_output)
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.cleanup()
|
self.cleanup()
|
||||||
|
|
||||||
|
|
|
||||||
32
utils.py
32
utils.py
|
|
@ -16,6 +16,27 @@
|
||||||
import csv
|
import csv
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
from io import StringIO
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
# Ref. https://stackoverflow.com/a/16571630
|
||||||
|
class Capturing(list):
|
||||||
|
'''Capture stdout and stderr
|
||||||
|
Usage:
|
||||||
|
with Capturing() as output:
|
||||||
|
print("Output")
|
||||||
|
'''
|
||||||
|
def __enter__(self):
|
||||||
|
self._stdout = sys.stdout
|
||||||
|
sys.stdout = self._stringio = StringIO()
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, *args):
|
||||||
|
self.extend(self._stringio.getvalue().splitlines())
|
||||||
|
del self._stringio # free up some memory
|
||||||
|
sys.stdout = self._stdout
|
||||||
|
|
||||||
|
|
||||||
def remove_file(filename):
|
def remove_file(filename):
|
||||||
if os.path.exists(filename): os.remove(filename)
|
if os.path.exists(filename): os.remove(filename)
|
||||||
|
|
@ -35,3 +56,14 @@ def read_json(filename):
|
||||||
"""Returns a list or a dictionary."""
|
"""Returns a list or a dictionary."""
|
||||||
with open(filename, "r") as infile:
|
with open(filename, "r") as infile:
|
||||||
return json.load(infile)
|
return json.load(infile)
|
||||||
|
|
||||||
|
|
||||||
|
def read_file_to_list(filename):
|
||||||
|
"""Returns a list of lines."""
|
||||||
|
with open(filename, "r") as infile:
|
||||||
|
return infile.readlines()
|
||||||
|
|
||||||
|
|
||||||
|
def read_file_to_str(filename):
|
||||||
|
"""Returns a str."""
|
||||||
|
return "".join(read_file_to_list(filename))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue