Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix:unittests #2

Merged
merged 2 commits into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions .github/workflows/unittests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Run UnitTests
on:
pull_request:
branches:
- dev
paths-ignore:
- 'z85base91/version.py'
- '.github/**'
- '.gitignore'
- 'LICENSE'
- 'CHANGELOG.md'
- 'MANIFEST.in'
- 'README.md'
push:
branches:
- master
paths-ignore:
- 'z85base91/version.py'
- '.github/**'
- '.gitignore'
- 'LICENSE'
- 'CHANGELOG.md'
- 'MANIFEST.in'
- 'README.md'
workflow_dispatch:

jobs:
unit_tests:
strategy:
matrix:
python-version: ["3.10", "3.11" ]
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v2
- name: Set up python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
Comment on lines +35 to +39
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Update GitHub Actions to their latest versions

Several actions are using outdated versions:

  • actions/checkout@v2v4
  • actions/setup-python@v2v5
  • codecov/codecov-action@v2v4
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v4
-        uses: actions/setup-python@v2
+        uses: actions/setup-python@v5
-        uses: codecov/codecov-action@v2
+        uses: codecov/codecov-action@v4

Also applies to: 56-58

🧰 Tools
🪛 actionlint (1.7.4)

35-35: the runner of "actions/checkout@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)


37-37: the runner of "actions/setup-python@v2" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

- name: Install System Dependencies
run: |
sudo apt-get update
sudo apt install python3-dev swig
python -m pip install build wheel
- name: Install repo
run: |
pip install -e .
- name: Install test dependencies
run: |
pip install -r test/requirements.txt
- name: Run unittests
run: |
pytest --cov=z85base91 --cov-report xml test
- name: Upload coverage
if: "${{ matrix.python-version == '3.11' }}"
env:
CODECOV_TOKEN: ${{secrets.CODECOV_TOKEN}}
uses: codecov/codecov-action@v2
Empty file added test/__init__.py
Empty file.
2 changes: 2 additions & 0 deletions test/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pytest~=7.1
pytest-cov~=4.1
62 changes: 62 additions & 0 deletions test/test_b91.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import unittest
from z85base91 import B91


class TestB91(unittest.TestCase):
def test_encode_empty(self):
"""Test encoding an empty byte sequence."""
self.assertEqual(B91.encode(b''), b'')
self.assertEqual(B91.encode(''), b'')

def test_decode_empty(self):
"""Test decoding an empty string."""
self.assertEqual(B91.decode(''), b'')
self.assertEqual(B91.decode(b''), b'')

def test_encode_single_byte(self):
"""Test encoding a single byte."""
self.assertEqual(b'A', B91.decode(B91.encode(b'A')))
self.assertEqual(b'B', B91.decode(B91.encode('B')))
self.assertEqual(b'_~', B91.decode(B91.encode(b'_~')))
self.assertEqual(b'_~', B91.decode(B91.encode('_~')))

def test_encode_short_string(self):
"""Test encoding a short string."""
self.assertEqual(b'hello', B91.decode(B91.encode(b'hello')))
self.assertEqual(B91.decode('>OwJh>Io0Tv!lE'), b'Hello World')

def test_encode_decode_round_trip(self):
"""Test encoding and decoding round-trip."""
data = b'The quick brown fox jumps over the lazy dog.'
encoded = B91.encode(data)
decoded = B91.decode(encoded)
self.assertEqual(decoded, data)

def test_encode_unicode_string(self):
"""Test encoding a Unicode string."""
data = 'こんにちは' # Japanese for "hello"
encoded = B91.encode(data)
decoded = B91.decode(encoded)
self.assertEqual(decoded.decode('utf-8'), data)

def test_decode_invalid_character(self):
"""Test decoding with invalid Base91 characters."""
with self.assertRaises(ValueError):
B91.decode('Invalid🎉Chars')

def test_3bytes_threshold(self):
"""Test edge cases around the 88 threshold."""
data = b'\x00\x00\x00' # Minimal data
encoded = B91.encode(data)
self.assertEqual(B91.decode(encoded), data)

def test_encode_large_data(self):
"""Test encoding a large byte sequence."""
data = b'\xff' * 1000
encoded = B91.encode(data)
decoded = B91.decode(encoded)
self.assertEqual(decoded, data)


if __name__ == '__main__':
unittest.main()
62 changes: 62 additions & 0 deletions test/test_z85b.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import unittest
from z85base91 import Z85B


class TestZ85B(unittest.TestCase):
def test_encode_empty(self):
"""Test encoding an empty byte sequence."""
self.assertEqual(Z85B.encode(b''), b'')
self.assertEqual(Z85B.encode(''), b'')

def test_decode_empty(self):
"""Test decoding an empty string."""
self.assertEqual(Z85B.decode(''), b'')
self.assertEqual(Z85B.decode(b''), b'')

def test_encode_single_byte(self):
"""Test encoding a single byte."""
self.assertEqual(b'A', Z85B.decode(Z85B.encode(b'A')))
self.assertEqual(b'B', Z85B.decode(Z85B.encode('B')))
self.assertEqual(b'_~', Z85B.decode(Z85B.encode(b'_~')))
self.assertEqual(b'_~', Z85B.decode(Z85B.encode('_~')))

def test_encode_short_string(self):
"""Test encoding a short string."""
self.assertEqual(b'hello', Z85B.decode(Z85B.encode(b'hello')))
self.assertEqual(b'Hello World', Z85B.decode(Z85B.encode(b'Hello World')))

def test_encode_decode_round_trip(self):
"""Test encoding and decoding round-trip."""
data = b'The quick brown fox jumps over the lazy dog.'
encoded = Z85B.encode(data)
decoded = Z85B.decode(encoded)
self.assertEqual(decoded, data)

def test_encode_unicode_string(self):
"""Test encoding a Unicode string."""
data = 'こんにちは' # Japanese for "hello"
encoded = Z85B.encode(data)
decoded = Z85B.decode(encoded)
self.assertEqual(decoded.decode('utf-8'), data)

def test_decode_invalid_character(self):
"""Test decoding with invalid Base91 characters."""
with self.assertRaises(ValueError):
Z85B.decode('Invalid🎉Chars')

def test_edge_case_88_threshold(self):
"""Test edge cases around the 88 threshold."""
data = b'\x00\x00\x00' # Minimal data
encoded = Z85B.encode(data)
self.assertEqual(Z85B.decode(encoded), data)

def test_encode_large_data(self):
"""Test encoding a large byte sequence."""
data = b'\xff' * 1000
encoded = Z85B.encode(data)
decoded = Z85B.decode(encoded)
self.assertEqual(decoded, data)


if __name__ == '__main__':
unittest.main()
104 changes: 104 additions & 0 deletions test/test_z85p.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import unittest
from z85base91 import Z85P


class TestZ85P(unittest.TestCase):
def test_encode_empty(self):
"""Test encoding an empty byte sequence."""
self.assertEqual(Z85P.encode(b''), b'\x00')
self.assertEqual(Z85P.encode(''), b'\x00')

def test_decode_empty(self):
"""Test decoding an empty string."""
self.assertEqual(Z85P.decode(b'\x00'), b'')
self.assertEqual(Z85P.decode(''), b'')
self.assertEqual(Z85P.decode(b''), b'')

def test_encode_single_byte(self):
"""Test encoding a single byte."""
self.assertEqual(b'A', Z85P.decode(Z85P.encode(b'A')))
self.assertEqual(b'B', Z85P.decode(Z85P.encode('B')))
self.assertEqual(b'_~', Z85P.decode(Z85P.encode(b'_~')))
self.assertEqual(b'_~', Z85P.decode(Z85P.encode('_~')))

def test_encode_short_string(self):
"""Test encoding a short string."""
self.assertEqual(b'hello', Z85P.decode(Z85P.encode(b'hello')))

def test_encode_decode_round_trip(self):
"""Test encoding and decoding round-trip."""
data = b'The quick brown fox jumps over the lazy dog.'
encoded = Z85P.encode(data)
decoded = Z85P.decode(encoded)
self.assertEqual(decoded, data)

def test_encode_unicode_string(self):
"""Test encoding a Unicode string."""
data = 'こんにちは' # Japanese for "hello"
encoded = Z85P.encode(data)
decoded = Z85P.decode(encoded)
self.assertEqual(decoded.decode('utf-8'), data)

def test_decode_invalid_character(self):
"""Test decoding with invalid z85 characters."""
with self.assertRaises(ValueError):
Z85P.decode('Invalid🎉Chars')
JarbasAl marked this conversation as resolved.
Show resolved Hide resolved

def test_encode_large_data(self):
"""Test encoding a large byte sequence."""
data = b'\xff' * 1000
encoded = Z85P.encode(data)
decoded = Z85P.decode(encoded)
self.assertEqual(decoded, data)

def test_padding_single_byte(self):
"""Test encoding and decoding with one byte that requires padding."""
data = b'\x01' # Single byte, should get padded with 3 \x00 bytes
encoded = Z85P.encode(data)
self.assertEqual(encoded[0], 3) # Check padding byte
self.assertEqual(Z85P.decode(encoded), data)

def test_padding_two_bytes(self):
"""Test encoding and decoding with two bytes that require padding."""
data = b'\x01\x01' # Two bytes, should get padded with 2 \x00 bytes
encoded = Z85P.encode(data)
self.assertEqual(encoded[0], 2) # Check padding byte
self.assertEqual(Z85P.decode(encoded), data)

def test_padding_three_bytes(self):
"""Test encoding and decoding with three bytes that require padding."""
data = b'\x01\x01\x01' # Three bytes, should get padded with 1 \x00 byte
encoded = Z85P.encode(data)
self.assertEqual(encoded[0], 1) # Check padding byte
self.assertEqual(Z85P.decode(encoded), data)

def test_no_padding_5_bytes(self): # fails
data = b'\x01\x01\x01\x01\x01' # 5 bytes
encoded = Z85P.encode(data)
self.assertEqual(encoded[0], 3) # Check padding byte
self.assertEqual(Z85P.decode(encoded), data)
JarbasAl marked this conversation as resolved.
Show resolved Hide resolved

def test_no_padding_needed(self):
"""Test encoding and decoding with data that doesn't need padding."""
data = b'\x01\x01\x01\x01' # Exactly 4 bytes, no padding
encoded = Z85P.encode(data)
self.assertEqual(encoded[0], 0) # No padding
self.assertEqual(Z85P.decode(encoded), data)

def test_round_trip_padding(self):
"""Test round-trip encoding and decoding with padding."""
data = b'\x01\x01\x01' # Less than 4 bytes, needs padding
encoded = Z85P.encode(data)
decoded = Z85P.decode(encoded)
self.assertEqual(decoded, data) # Ensure padding is correctly removed

def test_padding_removal_after_decoding(self):
"""Test ensuring padding is correctly removed after decoding."""
data = b'\x01\x01\x01' # Less than 4 bytes, needs padding
encoded = Z85P.encode(data)
self.assertEqual(encoded[0], 1) # Padding size is 1
decoded = Z85P.decode(encoded)
self.assertEqual(decoded, data) # Padding should be removed

if __name__ == '__main__':
unittest.main()
Loading
Loading