A whoooole lotta 4.0.x fixes.
This commit is contained in:
@@ -1,525 +0,0 @@
|
||||
# Stegasoo v3.2.0 Release Checklist
|
||||
|
||||
## Overview
|
||||
|
||||
This checklist covers comprehensive functionality testing for the v3.2.0 release, which introduces breaking changes from v3.1.x.
|
||||
|
||||
### Breaking Changes in v3.2.0
|
||||
|
||||
| Change | v3.1.x | v3.2.0 |
|
||||
|--------|--------|--------|
|
||||
| Passphrase model | 7 daily phrases (`day_phrase`) | Single `passphrase` |
|
||||
| Date parameter | Required `date_str` | Removed |
|
||||
| Default words | 3 | 4 |
|
||||
| Format version | 3 | 4 |
|
||||
| Backward compatible | N/A | ❌ Cannot decode v3.1.x images |
|
||||
|
||||
---
|
||||
|
||||
## 1. Core Library Tests
|
||||
|
||||
### 1.1 Key Generation (`src/stegasoo/keygen.py`)
|
||||
|
||||
- [ ] **generate_pin()** - Default 6 digits, no leading zero
|
||||
- [ ] **generate_pin(length=9)** - Custom length works
|
||||
- [ ] **generate_phrase(words=4)** - Default 4 words
|
||||
- [ ] **generate_phrase(words=6)** - Custom word count
|
||||
- [ ] **generate_credentials(use_pin=True)** - Returns single passphrase
|
||||
- [ ] **generate_credentials(use_rsa=True)** - RSA key generation
|
||||
- [ ] **generate_credentials(use_pin=False, use_rsa=False)** - Raises error
|
||||
- [ ] **Credentials.passphrase** - Single string, not dict
|
||||
- [ ] **Credentials.passphrase_entropy** - Correct entropy (4 words = 44 bits)
|
||||
- [ ] **Credentials.total_entropy** - Sum is correct
|
||||
|
||||
### 1.2 Encoding (`src/stegasoo/steganography.py`)
|
||||
|
||||
- [ ] **encode() with passphrase** - New parameter name works
|
||||
- [ ] **encode() without date_str** - No date parameter needed
|
||||
- [ ] **HEADER_OVERHEAD = 65** - Correct constant
|
||||
- [ ] **LSB mode** - Default, full color PNG output
|
||||
- [ ] **DCT mode** - Frequency domain embedding
|
||||
- [ ] **DCT + JPEG output** - Works correctly
|
||||
- [ ] **DCT + color mode** - Preserves colors
|
||||
- [ ] **Capacity calculation** - Uses 65-byte overhead
|
||||
|
||||
### 1.3 Decoding (`src/stegasoo/steganography.py`)
|
||||
|
||||
- [ ] **decode() with passphrase** - New parameter name works
|
||||
- [ ] **decode() without date_str** - No date parameter needed
|
||||
- [ ] **Auto mode detection** - LSB vs DCT automatic
|
||||
- [ ] **Wrong passphrase** - Raises DecryptionError
|
||||
- [ ] **Wrong PIN** - Raises DecryptionError
|
||||
- [ ] **Wrong reference photo** - Raises DecryptionError
|
||||
|
||||
### 1.4 DCT Steganography (`src/stegasoo/dct_steganography.py`)
|
||||
|
||||
- [ ] **Y channel extraction** - Uses correct formula (not just R channel)
|
||||
- [ ] **Color mode encoding** - YCbCr conversion works
|
||||
- [ ] **Grayscale mode** - Converts to grayscale
|
||||
- [ ] **JPEG output** - Quality 95, proper format
|
||||
- [ ] **PNG output** - Lossless DCT output
|
||||
|
||||
### 1.5 Batch Processing (`src/stegasoo/batch.py`)
|
||||
|
||||
- [ ] **BatchCredentials.passphrase** - Single field, not dict
|
||||
- [ ] **BatchCredentials.from_dict()** - Accepts both old and new format
|
||||
- [ ] **batch_encode()** - Uses passphrase parameter
|
||||
- [ ] **batch_decode()** - Uses passphrase parameter
|
||||
|
||||
### 1.6 Validation
|
||||
|
||||
- [ ] **validate_passphrase()** - New function works
|
||||
- [ ] **validate_passphrase() warning** - Warns if < 4 words
|
||||
- [ ] **validate_pin()** - 6-9 digits, no leading zero
|
||||
- [ ] **validate_message()** - Non-empty, within size limits
|
||||
|
||||
---
|
||||
|
||||
## 2. CLI Frontend Tests (`frontends/cli/main.py`)
|
||||
|
||||
### 2.1 Generate Command
|
||||
|
||||
```bash
|
||||
# Test default generation (4 words, PIN)
|
||||
stegasoo generate --pin
|
||||
|
||||
# Test custom word count
|
||||
stegasoo generate --pin --words 6
|
||||
|
||||
# Test RSA generation
|
||||
stegasoo generate --rsa
|
||||
|
||||
# Test JSON output
|
||||
stegasoo generate --pin --json
|
||||
```
|
||||
|
||||
- [ ] Output shows single `PASSPHRASE:` not daily phrases
|
||||
- [ ] Default is 4 words
|
||||
- [ ] JSON has `passphrase` field, not `phrases` dict
|
||||
- [ ] Entropy shows `passphrase_entropy`
|
||||
|
||||
### 2.2 Encode Command
|
||||
|
||||
```bash
|
||||
# Test basic encode
|
||||
stegasoo encode -r ref.jpg -c carrier.png \
|
||||
-p "word1 word2 word3 word4" --pin 123456 \
|
||||
-m "Secret message"
|
||||
|
||||
# Test DCT mode
|
||||
stegasoo encode -r ref.jpg -c carrier.png \
|
||||
-p "word1 word2 word3 word4" --pin 123456 \
|
||||
-m "Secret" --mode dct
|
||||
|
||||
# Test DCT + JPEG
|
||||
stegasoo encode -r ref.jpg -c carrier.png \
|
||||
-p "word1 word2 word3 word4" --pin 123456 \
|
||||
-m "Secret" --mode dct --dct-format jpeg
|
||||
```
|
||||
|
||||
- [ ] `-p` / `--passphrase` parameter works
|
||||
- [ ] No `--date` parameter exists
|
||||
- [ ] LSB mode produces PNG
|
||||
- [ ] DCT mode works
|
||||
- [ ] DCT + JPEG output works
|
||||
- [ ] Output filename has no date suffix
|
||||
|
||||
### 2.3 Decode Command
|
||||
|
||||
```bash
|
||||
# Test basic decode
|
||||
stegasoo decode -r ref.jpg -s stego.png \
|
||||
-p "word1 word2 word3 word4" --pin 123456
|
||||
|
||||
# Test auto mode detection
|
||||
stegasoo decode -r ref.jpg -s stego.png \
|
||||
-p "word1 word2 word3 word4" --pin 123456 --mode auto
|
||||
```
|
||||
|
||||
- [ ] `-p` / `--passphrase` parameter works
|
||||
- [ ] No `--date` parameter exists
|
||||
- [ ] Auto-detects LSB vs DCT
|
||||
- [ ] Outputs decoded message
|
||||
|
||||
### 2.4 Other Commands
|
||||
|
||||
```bash
|
||||
# Verify command
|
||||
stegasoo verify -s stego.png
|
||||
|
||||
# Compare command
|
||||
stegasoo compare original.png stego.png
|
||||
|
||||
# Modes command
|
||||
stegasoo modes
|
||||
|
||||
# Capacity command
|
||||
stegasoo capacity carrier.png
|
||||
```
|
||||
|
||||
- [ ] All commands work without errors
|
||||
- [ ] No references to "day phrase" or dates
|
||||
|
||||
---
|
||||
|
||||
## 3. API Frontend Tests (`frontends/api/main.py`)
|
||||
|
||||
### 3.1 Status Endpoint
|
||||
|
||||
```bash
|
||||
curl http://localhost:8000/
|
||||
```
|
||||
|
||||
- [ ] Returns `version: "3.2.0"`
|
||||
- [ ] Includes `breaking_changes` object
|
||||
- [ ] No `day_names` field
|
||||
|
||||
### 3.2 Generate Endpoint
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/generate \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"use_pin": true, "words_per_passphrase": 4}'
|
||||
```
|
||||
|
||||
- [ ] Parameter is `words_per_passphrase` (not `words_per_phrase`)
|
||||
- [ ] Response has `passphrase` string field
|
||||
- [ ] Response has `phrases: null`
|
||||
- [ ] Entropy field is `passphrase` not `phrase`
|
||||
|
||||
### 3.3 Encode Endpoint
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/encode \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"message": "Secret",
|
||||
"passphrase": "word1 word2 word3 word4",
|
||||
"pin": "123456",
|
||||
"reference_photo_base64": "...",
|
||||
"carrier_image_base64": "..."
|
||||
}'
|
||||
```
|
||||
|
||||
- [ ] Parameter is `passphrase` (not `day_phrase`)
|
||||
- [ ] No `date_str` parameter accepted
|
||||
- [ ] Response has `date_used: null`
|
||||
- [ ] Response has `day_of_week: null`
|
||||
|
||||
### 3.4 Decode Endpoint
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/decode \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"passphrase": "word1 word2 word3 word4",
|
||||
"pin": "123456",
|
||||
"stego_image_base64": "...",
|
||||
"reference_photo_base64": "..."
|
||||
}'
|
||||
```
|
||||
|
||||
- [ ] Parameter is `passphrase` (not `day_phrase`)
|
||||
- [ ] No `date_str` parameter needed
|
||||
- [ ] Auto-detects embedding mode
|
||||
|
||||
### 3.5 Multipart Endpoints
|
||||
|
||||
```bash
|
||||
# Encode multipart
|
||||
curl -X POST http://localhost:8000/encode/multipart \
|
||||
-F "passphrase=word1 word2 word3 word4" \
|
||||
-F "pin=123456" \
|
||||
-F "message=Secret" \
|
||||
-F "reference_photo=@ref.jpg" \
|
||||
-F "carrier=@carrier.png"
|
||||
|
||||
# Decode multipart
|
||||
curl -X POST http://localhost:8000/decode/multipart \
|
||||
-F "passphrase=word1 word2 word3 word4" \
|
||||
-F "pin=123456" \
|
||||
-F "reference_photo=@ref.jpg" \
|
||||
-F "stego_image=@stego.png"
|
||||
```
|
||||
|
||||
- [ ] Form field is `passphrase` (not `day_phrase`)
|
||||
- [ ] No `date_str` field
|
||||
- [ ] Headers include `X-Stegasoo-Version: 3.2.0`
|
||||
- [ ] No date headers in response
|
||||
|
||||
---
|
||||
|
||||
## 4. Web Frontend Tests (`frontends/web/app.py`)
|
||||
|
||||
### 4.1 Generate Page (`/generate`)
|
||||
|
||||
- [ ] Form field is `words_per_passphrase`
|
||||
- [ ] Default slider value is 4
|
||||
- [ ] Output shows single passphrase, not 7 daily phrases
|
||||
- [ ] Memory aid works with single passphrase
|
||||
- [ ] Entropy display shows `passphrase_entropy`
|
||||
- [ ] v3.2.0 badge visible
|
||||
|
||||
### 4.2 Encode Page (`/encode`)
|
||||
|
||||
- [ ] Form field is `passphrase`
|
||||
- [ ] No date selection field
|
||||
- [ ] v3.2.0 badge on passphrase label
|
||||
- [ ] Passphrase validation warning works (< 4 words)
|
||||
- [ ] DCT mode options work
|
||||
- [ ] Success result shows no date info
|
||||
|
||||
### 4.3 Decode Page (`/decode`)
|
||||
|
||||
- [ ] Form field is `passphrase`
|
||||
- [ ] No date input field
|
||||
- [ ] No date detection from filename JavaScript
|
||||
- [ ] Troubleshooting mentions v3.2.0 compatibility
|
||||
- [ ] Auto mode detection works
|
||||
|
||||
### 4.4 Other Pages
|
||||
|
||||
- [ ] **Home** (`/`) - Shows v3.2.0 badge, passphrase terminology
|
||||
- [ ] **About** (`/about`) - Updated terminology, v3.2.0 features
|
||||
- [ ] **Footer** - Says "Passphrase" not "Day-Phrase"
|
||||
|
||||
---
|
||||
|
||||
## 5. Integration Tests
|
||||
|
||||
### 5.1 Full Roundtrip Tests
|
||||
|
||||
```bash
|
||||
# Generate → Encode → Decode (LSB)
|
||||
stegasoo generate --pin > creds.json
|
||||
stegasoo encode -r ref.jpg -c carrier.png -p "..." --pin 123456 -m "Test" -o stego.png
|
||||
stegasoo decode -r ref.jpg -s stego.png -p "..." --pin 123456
|
||||
|
||||
# Generate → Encode → Decode (DCT)
|
||||
stegasoo encode -r ref.jpg -c carrier.png -p "..." --pin 123456 -m "Test" --mode dct -o stego_dct.png
|
||||
stegasoo decode -r ref.jpg -s stego_dct.png -p "..." --pin 123456
|
||||
```
|
||||
|
||||
- [ ] LSB roundtrip works
|
||||
- [ ] DCT roundtrip works
|
||||
- [ ] DCT + JPEG roundtrip works
|
||||
- [ ] File embedding roundtrip works
|
||||
|
||||
### 5.2 Cross-Frontend Tests
|
||||
|
||||
- [ ] Encode via CLI, decode via API
|
||||
- [ ] Encode via API, decode via Web
|
||||
- [ ] Encode via Web, decode via CLI
|
||||
|
||||
### 5.3 Error Handling
|
||||
|
||||
- [ ] Wrong passphrase shows clear error
|
||||
- [ ] Wrong PIN shows clear error
|
||||
- [ ] Wrong reference photo shows clear error
|
||||
- [ ] Capacity exceeded shows clear error
|
||||
- [ ] Invalid image shows clear error
|
||||
|
||||
---
|
||||
|
||||
## 6. Documentation Tests
|
||||
|
||||
### 6.1 CLI Documentation (`frontends/CLI.md`)
|
||||
|
||||
- [ ] "What's New in v3.2.0" section exists
|
||||
- [ ] All examples use 4-word passphrases
|
||||
- [ ] No `--date` parameter in examples
|
||||
- [ ] Command reference is complete
|
||||
- [ ] Migration notes for v3.1.x users
|
||||
|
||||
### 6.2 API Documentation (`frontends/API.md`)
|
||||
|
||||
- [ ] "What's New in v3.2.0" section exists
|
||||
- [ ] All request examples use `passphrase`
|
||||
- [ ] No `date_str` in request models
|
||||
- [ ] Response models show `date_used: null`
|
||||
- [ ] Code examples updated
|
||||
|
||||
### 6.3 Web UI Documentation (`frontends/WEB_UI.md`)
|
||||
|
||||
- [ ] "What's New in v3.2.0" section exists
|
||||
- [ ] Workflow examples use passphrase
|
||||
- [ ] No date selection in screenshots/descriptions
|
||||
- [ ] Troubleshooting updated
|
||||
|
||||
---
|
||||
|
||||
## 7. Backward Compatibility Tests
|
||||
|
||||
### 7.1 v3.1.x Image Decoding
|
||||
|
||||
- [ ] Attempting to decode v3.1.x image with v3.2.0 fails gracefully
|
||||
- [ ] Error message mentions version incompatibility
|
||||
- [ ] Suggests using v3.1.x for old images
|
||||
|
||||
### 7.2 Migration Path
|
||||
|
||||
- [ ] `BatchCredentials.from_dict()` accepts old `day_phrase` key
|
||||
- [ ] `generate_credentials_legacy()` available if needed
|
||||
- [ ] Documentation explains migration steps
|
||||
|
||||
---
|
||||
|
||||
## 8. Unit Test Updates
|
||||
|
||||
### 8.1 Test Files to Update
|
||||
|
||||
- [ ] `tests/test_stegasoo.py` - Use `passphrase` parameter
|
||||
- [ ] `tests/test_batch.py` - Use `passphrase` in credentials
|
||||
- [ ] `tests/test_compression.py` - No changes needed (compression unchanged)
|
||||
|
||||
### 8.2 New Tests Needed
|
||||
|
||||
- [ ] Test single passphrase generation
|
||||
- [ ] Test `passphrase_words` parameter
|
||||
- [ ] Test `validate_passphrase()` function
|
||||
- [ ] Test DCT Y channel extraction
|
||||
- [ ] Test 65-byte header overhead
|
||||
|
||||
---
|
||||
|
||||
## 9. Release Artifacts
|
||||
|
||||
### 9.1 Version Bumps
|
||||
|
||||
- [ ] `src/stegasoo/constants.py` - `__version__ = "3.2.0"`
|
||||
- [ ] `pyproject.toml` or `setup.py` - version updated
|
||||
- [ ] `CHANGELOG.md` - v3.2.0 section added
|
||||
|
||||
### 9.2 Documentation
|
||||
|
||||
- [ ] `README.md` - Updated for v3.2.0
|
||||
- [ ] `frontends/CLI.md` - Complete
|
||||
- [ ] `frontends/API.md` - Complete
|
||||
- [ ] `frontends/WEB_UI.md` - Complete
|
||||
|
||||
### 9.3 Git
|
||||
|
||||
- [ ] All changes committed
|
||||
- [ ] Tag created: `v3.2.0`
|
||||
- [ ] Release notes written
|
||||
|
||||
---
|
||||
|
||||
## 10. Quick Smoke Test Script
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# v3.2.0 Smoke Test
|
||||
|
||||
set -e
|
||||
|
||||
echo "=== Stegasoo v3.2.0 Smoke Test ==="
|
||||
|
||||
# Check version
|
||||
echo "1. Checking version..."
|
||||
python -c "import stegasoo; print(f'Version: {stegasoo.__version__}')"
|
||||
|
||||
# Generate credentials
|
||||
echo "2. Generating credentials..."
|
||||
python -c "
|
||||
from stegasoo import generate_credentials
|
||||
creds = generate_credentials(use_pin=True, passphrase_words=4)
|
||||
print(f'Passphrase: {creds.passphrase}')
|
||||
print(f'PIN: {creds.pin}')
|
||||
print(f'Entropy: {creds.total_entropy} bits')
|
||||
assert ' ' in creds.passphrase, 'Passphrase should have spaces'
|
||||
assert len(creds.passphrase.split()) == 4, 'Should have 4 words'
|
||||
print('✓ Credentials OK')
|
||||
"
|
||||
|
||||
# Test encode/decode roundtrip
|
||||
echo "3. Testing encode/decode roundtrip..."
|
||||
python -c "
|
||||
from stegasoo import encode, decode
|
||||
from PIL import Image
|
||||
import io
|
||||
|
||||
# Create test image
|
||||
img = Image.new('RGB', (200, 200), color='blue')
|
||||
buf = io.BytesIO()
|
||||
img.save(buf, format='PNG')
|
||||
test_image = buf.getvalue()
|
||||
|
||||
# Encode
|
||||
result = encode(
|
||||
message='Hello v3.2.0!',
|
||||
reference_photo=test_image,
|
||||
carrier_image=test_image,
|
||||
passphrase='test phrase four words',
|
||||
pin='123456'
|
||||
)
|
||||
print(f'Encoded: {result.filename}')
|
||||
|
||||
# Decode
|
||||
decoded = decode(
|
||||
stego_image=result.stego_image,
|
||||
reference_photo=test_image,
|
||||
passphrase='test phrase four words',
|
||||
pin='123456'
|
||||
)
|
||||
assert decoded.message == 'Hello v3.2.0!', 'Message mismatch'
|
||||
print(f'Decoded: {decoded.message}')
|
||||
print('✓ Roundtrip OK')
|
||||
"
|
||||
|
||||
# Test DCT mode
|
||||
echo "4. Testing DCT mode..."
|
||||
python -c "
|
||||
from stegasoo import encode, decode, has_dct_support
|
||||
if has_dct_support():
|
||||
from PIL import Image
|
||||
import io
|
||||
|
||||
img = Image.new('RGB', (200, 200), color='green')
|
||||
buf = io.BytesIO()
|
||||
img.save(buf, format='PNG')
|
||||
test_image = buf.getvalue()
|
||||
|
||||
result = encode(
|
||||
message='DCT test',
|
||||
reference_photo=test_image,
|
||||
carrier_image=test_image,
|
||||
passphrase='dct test phrase here',
|
||||
pin='123456',
|
||||
embed_mode='dct'
|
||||
)
|
||||
|
||||
decoded = decode(
|
||||
stego_image=result.stego_image,
|
||||
reference_photo=test_image,
|
||||
passphrase='dct test phrase here',
|
||||
pin='123456'
|
||||
)
|
||||
assert decoded.message == 'DCT test'
|
||||
print('✓ DCT Mode OK')
|
||||
else:
|
||||
print('⚠ DCT mode not available (scipy not installed)')
|
||||
"
|
||||
|
||||
echo ""
|
||||
echo "=== All smoke tests passed! ==="
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sign-Off
|
||||
|
||||
| Area | Tested By | Date | Status |
|
||||
|------|-----------|------|--------|
|
||||
| Core Library | | | ☐ |
|
||||
| CLI Frontend | | | ☐ |
|
||||
| API Frontend | | | ☐ |
|
||||
| Web Frontend | | | ☐ |
|
||||
| Documentation | | | ☐ |
|
||||
| Integration | | | ☐ |
|
||||
|
||||
**Release Approved:** ☐
|
||||
|
||||
**Released By:** _________________
|
||||
|
||||
**Release Date:** _________________
|
||||
528
tests/RELEASE_CHECKLIST_V4_0_0.md
Normal file
528
tests/RELEASE_CHECKLIST_V4_0_0.md
Normal file
@@ -0,0 +1,528 @@
|
||||
# Stegasoo v4.0.0 Release Checklist
|
||||
|
||||
## Overview
|
||||
|
||||
This checklist covers functionality testing for the v4.0.0 release.
|
||||
|
||||
### Changes in v4.0.0
|
||||
|
||||
| Change | v3.2.0 | v4.0.0 |
|
||||
|--------|--------|--------|
|
||||
| Python version | 3.10-3.12 | 3.10-3.12 (3.13 NOT supported) |
|
||||
| JPEG handling | Could crash on quality=100 | Normalized before jpegio |
|
||||
| Header size | 65 bytes | 65 bytes (unchanged) |
|
||||
| API | passphrase, no date_str | Same (no breaking changes) |
|
||||
| Format version | 4 | 4 (compatible with v3.2.0) |
|
||||
|
||||
### Key Points
|
||||
- **No breaking API changes from v3.2.0**
|
||||
- **v4.0 CAN decode v3.2.0 images** (same format version)
|
||||
- **v4.0 CANNOT decode v3.1.x or earlier images**
|
||||
- **Python 3.13 is NOT supported** (jpegio C extension ABI incompatibility)
|
||||
|
||||
---
|
||||
|
||||
## 1. Pre-Release Checks
|
||||
|
||||
### 1.1 Python Version
|
||||
|
||||
```bash
|
||||
python --version # Must be 3.10, 3.11, or 3.12
|
||||
```
|
||||
|
||||
- [ ] Python version is 3.10, 3.11, or 3.12
|
||||
- [ ] NOT Python 3.13 (jpegio will crash)
|
||||
|
||||
### 1.2 Dependencies
|
||||
|
||||
```bash
|
||||
pip list | grep -E "jpegio|scipy|pillow|argon2"
|
||||
```
|
||||
|
||||
- [ ] jpegio installed (for DCT JPEG support)
|
||||
- [ ] scipy installed (for DCT mode)
|
||||
- [ ] pillow installed
|
||||
- [ ] argon2-cffi installed
|
||||
|
||||
---
|
||||
|
||||
## 2. Core Library Tests
|
||||
|
||||
### 2.1 Run Unit Tests
|
||||
|
||||
```bash
|
||||
cd /path/to/stegasoo
|
||||
pytest tests/ -v
|
||||
```
|
||||
|
||||
- [ ] All tests pass
|
||||
- [ ] No deprecation warnings for removed parameters
|
||||
|
||||
### 2.2 JPEG Normalization Test (NEW in v4.0)
|
||||
|
||||
```bash
|
||||
python -c "
|
||||
from PIL import Image
|
||||
import io
|
||||
from stegasoo import encode, decode
|
||||
|
||||
# Create quality=100 JPEG (triggers normalization)
|
||||
img = Image.new('RGB', (400, 400), 'red')
|
||||
buf = io.BytesIO()
|
||||
img.save(buf, format='JPEG', quality=100)
|
||||
jpeg_data = buf.getvalue()
|
||||
|
||||
# This should NOT crash (v3.2.0 would crash here)
|
||||
result = encode(
|
||||
message='Test quality 100',
|
||||
reference_photo=jpeg_data,
|
||||
carrier_image=jpeg_data,
|
||||
passphrase='test phrase four words',
|
||||
pin='123456',
|
||||
embed_mode='dct'
|
||||
)
|
||||
print('✓ Quality=100 JPEG encode OK')
|
||||
|
||||
decoded = decode(
|
||||
stego_image=result.stego_image,
|
||||
reference_photo=jpeg_data,
|
||||
passphrase='test phrase four words',
|
||||
pin='123456'
|
||||
)
|
||||
assert decoded.message == 'Test quality 100'
|
||||
print('✓ Quality=100 JPEG decode OK')
|
||||
"
|
||||
```
|
||||
|
||||
- [ ] Quality=100 JPEG encoding works (no crash)
|
||||
- [ ] Quality=100 JPEG decoding works
|
||||
|
||||
### 2.3 Large Image Test (NEW in v4.0)
|
||||
|
||||
```bash
|
||||
python -c "
|
||||
from PIL import Image
|
||||
import io
|
||||
from stegasoo import encode, decode
|
||||
|
||||
# Create large image (similar to 14MB real photo)
|
||||
img = Image.new('RGB', (4000, 3000), 'blue')
|
||||
buf = io.BytesIO()
|
||||
img.save(buf, format='PNG')
|
||||
large_image = buf.getvalue()
|
||||
print(f'Test image size: {len(large_image) / 1024 / 1024:.1f} MB')
|
||||
|
||||
result = encode(
|
||||
message='Large image test',
|
||||
reference_photo=large_image,
|
||||
carrier_image=large_image,
|
||||
passphrase='large image test phrase',
|
||||
pin='123456'
|
||||
)
|
||||
print('✓ Large image encode OK')
|
||||
|
||||
decoded = decode(
|
||||
stego_image=result.stego_image,
|
||||
reference_photo=large_image,
|
||||
passphrase='large image test phrase',
|
||||
pin='123456'
|
||||
)
|
||||
assert decoded.message == 'Large image test'
|
||||
print('✓ Large image decode OK')
|
||||
"
|
||||
```
|
||||
|
||||
- [ ] Large image (12MP+) encoding works
|
||||
- [ ] Large image decoding works
|
||||
|
||||
---
|
||||
|
||||
## 3. Docker Build Tests
|
||||
|
||||
### 3.1 Base Image Build
|
||||
|
||||
```bash
|
||||
# Build base image (one-time, 5-10 min)
|
||||
sudo docker build -f Dockerfile.base -t stegasoo-base:latest .
|
||||
```
|
||||
|
||||
- [ ] Base image builds successfully
|
||||
- [ ] jpegio + scipy + numpy verification passes
|
||||
|
||||
### 3.2 Application Build
|
||||
|
||||
```bash
|
||||
# Fast build using base image
|
||||
sudo docker-compose build
|
||||
```
|
||||
|
||||
- [ ] Web container builds
|
||||
- [ ] API container builds
|
||||
|
||||
### 3.3 Container Startup
|
||||
|
||||
```bash
|
||||
sudo docker-compose up -d
|
||||
sudo docker-compose logs
|
||||
```
|
||||
|
||||
- [ ] Web container starts without errors
|
||||
- [ ] API container starts without errors
|
||||
- [ ] No import errors in logs
|
||||
|
||||
---
|
||||
|
||||
## 4. Web UI Tests (`http://localhost:5000`)
|
||||
|
||||
### 4.1 Home Page
|
||||
|
||||
- [ ] v4.0 badge visible
|
||||
- [ ] "Learn More" button is white/visible
|
||||
- [ ] No references to "day phrase" or dates
|
||||
|
||||
### 4.2 Generate Page (`/generate`)
|
||||
|
||||
- [ ] Default is 4 words
|
||||
- [ ] Single passphrase generated (not 7 daily)
|
||||
- [ ] PIN toggle shows/hides digits
|
||||
- [ ] Memory aid generator works
|
||||
|
||||
### 4.3 Encode Page (`/encode`)
|
||||
|
||||
- [ ] Passphrase field has blue glow on focus
|
||||
- [ ] PIN field has orange glow on focus
|
||||
- [ ] PIN box is 180px wide (fits LastPass icon)
|
||||
- [ ] Passphrase font shrinks for long input (stepped)
|
||||
- [ ] RSA .pem/QR toggle works
|
||||
- [ ] QR image preview shows when selected
|
||||
- [ ] DCT mode options appear when selected
|
||||
- [ ] Encoding works (LSB mode)
|
||||
- [ ] Encoding works (DCT mode)
|
||||
|
||||
### 4.4 Decode Page (`/decode`)
|
||||
|
||||
- [ ] Same styling as encode (glowing inputs)
|
||||
- [ ] RSA .pem/QR toggle works (matches encode layout)
|
||||
- [ ] QR image preview shows when selected
|
||||
- [ ] Copy button is below message (not overlapping)
|
||||
- [ ] Decoding works (LSB mode)
|
||||
- [ ] Decoding works (DCT mode)
|
||||
- [ ] Auto mode detection works
|
||||
|
||||
### 4.5 About Page (`/about`)
|
||||
|
||||
- [ ] Version history table present
|
||||
- [ ] v4.0.0 entry in table
|
||||
- [ ] Python 3.10-3.12 requirement noted
|
||||
- [ ] No marketing language ("military-grade" removed)
|
||||
|
||||
---
|
||||
|
||||
## 5. API Tests (`http://localhost:8000`)
|
||||
|
||||
### 5.1 Status Endpoint
|
||||
|
||||
```bash
|
||||
curl http://localhost:8000/
|
||||
```
|
||||
|
||||
- [ ] Returns version "4.0.0"
|
||||
- [ ] No import errors
|
||||
|
||||
### 5.2 Generate Endpoint
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:8000/generate \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"use_pin": true}'
|
||||
```
|
||||
|
||||
- [ ] Returns single `passphrase` string
|
||||
- [ ] Returns 4 words by default
|
||||
|
||||
### 5.3 OpenAPI Docs
|
||||
|
||||
- [ ] `/docs` loads (Swagger UI)
|
||||
- [ ] `/redoc` loads (ReDoc)
|
||||
- [ ] All endpoints documented
|
||||
|
||||
---
|
||||
|
||||
## 6. CLI Tests
|
||||
|
||||
### 6.1 Version
|
||||
|
||||
```bash
|
||||
stegasoo --version
|
||||
```
|
||||
|
||||
- [ ] Shows 4.0.0
|
||||
|
||||
### 6.2 Generate
|
||||
|
||||
```bash
|
||||
stegasoo generate --pin --words 4
|
||||
```
|
||||
|
||||
- [ ] Single passphrase output
|
||||
- [ ] 4 words generated
|
||||
|
||||
### 6.3 Encode/Decode Roundtrip
|
||||
|
||||
```bash
|
||||
# Generate test image
|
||||
python -c "from PIL import Image; Image.new('RGB', (200,200), 'red').save('/tmp/test.png')"
|
||||
|
||||
# Encode
|
||||
stegasoo encode \
|
||||
-r /tmp/test.png \
|
||||
-c /tmp/test.png \
|
||||
-p "cli test phrase here" \
|
||||
--pin 123456 \
|
||||
-m "CLI roundtrip test" \
|
||||
-o /tmp/stego.png
|
||||
|
||||
# Decode
|
||||
stegasoo decode \
|
||||
-r /tmp/test.png \
|
||||
-s /tmp/stego.png \
|
||||
-p "cli test phrase here" \
|
||||
--pin 123456
|
||||
```
|
||||
|
||||
- [ ] Encode succeeds
|
||||
- [ ] Decode returns correct message
|
||||
|
||||
---
|
||||
|
||||
## 7. Cross-Version Compatibility
|
||||
|
||||
### 7.1 v3.2.0 Compatibility
|
||||
|
||||
- [ ] v4.0 can decode v3.2.0 images (same format version 4)
|
||||
|
||||
### 7.2 v3.1.x Incompatibility
|
||||
|
||||
- [ ] v4.0 fails gracefully on v3.1.x images
|
||||
- [ ] Error message is clear
|
||||
|
||||
---
|
||||
|
||||
## 8. Documentation Review
|
||||
|
||||
### 8.1 Updated Files
|
||||
|
||||
- [ ] README.md - v4.0 references
|
||||
- [ ] INSTALL.md - Python 3.13 warning prominent
|
||||
- [ ] SECURITY.md - v4.0 changes documented
|
||||
- [ ] UNDER_THE_HOOD.md - JPEG normalization section
|
||||
|
||||
### 8.2 Template Updates
|
||||
|
||||
- [ ] All 7 templates updated
|
||||
- [ ] No v3.x badges remaining
|
||||
- [ ] Version history in About page
|
||||
|
||||
---
|
||||
|
||||
## 9. Quick Smoke Test Script
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# v4.0.0 Smoke Test
|
||||
|
||||
set -e
|
||||
|
||||
echo "=== Stegasoo v4.0.0 Smoke Test ==="
|
||||
|
||||
# Check version
|
||||
echo "1. Checking version..."
|
||||
python -c "import stegasoo; assert stegasoo.__version__.startswith('4.'), f'Wrong version: {stegasoo.__version__}'; print(f'✓ Version: {stegasoo.__version__}')"
|
||||
|
||||
# Check Python version
|
||||
echo "2. Checking Python version..."
|
||||
python -c "
|
||||
import sys
|
||||
v = sys.version_info
|
||||
assert v.major == 3 and 10 <= v.minor <= 12, f'Python {v.major}.{v.minor} not supported'
|
||||
print(f'✓ Python {v.major}.{v.minor}.{v.micro}')
|
||||
"
|
||||
|
||||
# Check DCT support
|
||||
echo "3. Checking DCT support..."
|
||||
python -c "
|
||||
from stegasoo import has_dct_support
|
||||
from stegasoo.dct_steganography import has_jpegio_support
|
||||
print(f' DCT (scipy): {has_dct_support()}')
|
||||
print(f' JPEG native (jpegio): {has_jpegio_support()}')
|
||||
assert has_dct_support(), 'DCT not available'
|
||||
print('✓ DCT support OK')
|
||||
"
|
||||
|
||||
# Test encode/decode roundtrip
|
||||
echo "4. Testing encode/decode roundtrip..."
|
||||
python -c "
|
||||
from stegasoo import encode, decode
|
||||
from PIL import Image
|
||||
import io
|
||||
|
||||
img = Image.new('RGB', (200, 200), color='blue')
|
||||
buf = io.BytesIO()
|
||||
img.save(buf, format='PNG')
|
||||
test_image = buf.getvalue()
|
||||
|
||||
result = encode(
|
||||
message='Hello v4.0.0!',
|
||||
reference_photo=test_image,
|
||||
carrier_image=test_image,
|
||||
passphrase='test phrase four words',
|
||||
pin='123456'
|
||||
)
|
||||
|
||||
decoded = decode(
|
||||
stego_image=result.stego_image,
|
||||
reference_photo=test_image,
|
||||
passphrase='test phrase four words',
|
||||
pin='123456'
|
||||
)
|
||||
|
||||
assert decoded.message == 'Hello v4.0.0!', f'Got: {decoded.message}'
|
||||
print('✓ LSB roundtrip OK')
|
||||
"
|
||||
|
||||
# Test DCT mode
|
||||
echo "5. Testing DCT mode..."
|
||||
python -c "
|
||||
from stegasoo import encode, decode
|
||||
from PIL import Image
|
||||
import io
|
||||
|
||||
img = Image.new('RGB', (400, 400), color='green')
|
||||
buf = io.BytesIO()
|
||||
img.save(buf, format='PNG')
|
||||
test_image = buf.getvalue()
|
||||
|
||||
result = encode(
|
||||
message='DCT v4.0 test',
|
||||
reference_photo=test_image,
|
||||
carrier_image=test_image,
|
||||
passphrase='dct test phrase here',
|
||||
pin='123456',
|
||||
embed_mode='dct'
|
||||
)
|
||||
|
||||
decoded = decode(
|
||||
stego_image=result.stego_image,
|
||||
reference_photo=test_image,
|
||||
passphrase='dct test phrase here',
|
||||
pin='123456'
|
||||
)
|
||||
|
||||
assert decoded.message == 'DCT v4.0 test'
|
||||
print('✓ DCT roundtrip OK')
|
||||
"
|
||||
|
||||
# Test JPEG quality=100 (v4.0 fix)
|
||||
echo "6. Testing JPEG quality=100 handling..."
|
||||
python -c "
|
||||
from stegasoo import encode, decode
|
||||
from PIL import Image
|
||||
import io
|
||||
|
||||
img = Image.new('RGB', (400, 400), color='red')
|
||||
buf = io.BytesIO()
|
||||
img.save(buf, format='JPEG', quality=100)
|
||||
jpeg_q100 = buf.getvalue()
|
||||
|
||||
result = encode(
|
||||
message='Quality 100 test',
|
||||
reference_photo=jpeg_q100,
|
||||
carrier_image=jpeg_q100,
|
||||
passphrase='jpeg quality test here',
|
||||
pin='123456',
|
||||
embed_mode='dct'
|
||||
)
|
||||
|
||||
decoded = decode(
|
||||
stego_image=result.stego_image,
|
||||
reference_photo=jpeg_q100,
|
||||
passphrase='jpeg quality test here',
|
||||
pin='123456'
|
||||
)
|
||||
|
||||
assert decoded.message == 'Quality 100 test'
|
||||
print('✓ JPEG quality=100 OK (v4.0 fix working)')
|
||||
"
|
||||
|
||||
echo ""
|
||||
echo "=== All smoke tests passed! ==="
|
||||
echo "Ready for release."
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Release Steps
|
||||
|
||||
### 10.1 Final Checks
|
||||
|
||||
- [ ] All tests pass
|
||||
- [ ] All Docker containers work
|
||||
- [ ] Documentation updated
|
||||
- [ ] Version bumped in `constants.py` and `pyproject.toml`
|
||||
|
||||
### 10.2 Git
|
||||
|
||||
```bash
|
||||
git add -A
|
||||
git status # Review changes
|
||||
git commit -m "v4.0.0: JPEG normalization, Python 3.12, UI polish"
|
||||
git tag v4.0.0
|
||||
git push origin main --tags
|
||||
```
|
||||
|
||||
- [ ] Changes committed
|
||||
- [ ] Tag created
|
||||
- [ ] Pushed to remote
|
||||
|
||||
### 10.3 Release Notes
|
||||
|
||||
```markdown
|
||||
## v4.0.0
|
||||
|
||||
### What's New
|
||||
- **JPEG Normalization**: Quality=100 JPEGs now work with DCT mode
|
||||
- **Python 3.12**: Recommended version (3.13 NOT supported due to jpegio)
|
||||
- **UI Polish**: Glowing input fields, better layout, version history
|
||||
|
||||
### Fixes
|
||||
- Fixed jpegio crash on quality=100 JPEG images
|
||||
- Fixed QR code input on decode page
|
||||
- Fixed passphrase font sizing (stepped instead of smooth)
|
||||
|
||||
### Breaking Changes
|
||||
- Python 3.13 is NOT supported
|
||||
|
||||
### Compatibility
|
||||
- v4.0 can decode v3.2.0 images (same format)
|
||||
- v4.0 CANNOT decode v3.1.x or earlier
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sign-Off
|
||||
|
||||
| Area | Tested By | Date | Status |
|
||||
|------|-----------|------|--------|
|
||||
| Python/Dependencies | | | ☐ |
|
||||
| Unit Tests | | | ☐ |
|
||||
| Docker Build | | | ☐ |
|
||||
| Web UI | | | ☐ |
|
||||
| API | | | ☐ |
|
||||
| CLI | | | ☐ |
|
||||
| Documentation | | | ☐ |
|
||||
|
||||
**Release Approved:** ☐
|
||||
|
||||
**Released By:** _________________
|
||||
|
||||
**Release Date:** _________________
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Tests for Stegasoo batch processing module (v3.2.0).
|
||||
Tests for Stegasoo batch processing module (v4.0.0).
|
||||
|
||||
Updated for v3.2.0:
|
||||
Updated for v4.0.0:
|
||||
- Uses 'passphrase' instead of 'phrase' in credentials dict
|
||||
- No date_str parameter
|
||||
- BatchCredentials.passphrase is a single string
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
"""
|
||||
Stegasoo Tests (v3.2.0)
|
||||
Stegasoo Tests (v4.0.0)
|
||||
|
||||
Tests for key generation, validation, encoding/decoding, and output formats.
|
||||
|
||||
Updated for v3.2.0:
|
||||
- Single passphrase instead of daily phrases
|
||||
- No date_str parameter
|
||||
- passphrase_words parameter (default 4)
|
||||
Updated for v4.0.0:
|
||||
- Same API as v3.2.0 (passphrase, no date_str)
|
||||
- JPEG normalization for jpegio compatibility
|
||||
- Python 3.12 recommended (3.13 not supported)
|
||||
"""
|
||||
|
||||
import pytest
|
||||
@@ -569,14 +569,11 @@ class TestVersion:
|
||||
assert len(parts) >= 2
|
||||
assert all(p.isdigit() for p in parts[:2])
|
||||
|
||||
def test_version_is_3_2_0(self):
|
||||
"""Version should be 3.2.0 or higher."""
|
||||
def test_version_is_4_0_0(self):
|
||||
"""Version should be 4.0.0 or higher."""
|
||||
parts = stegasoo.__version__.split('.')
|
||||
major = int(parts[0])
|
||||
minor = int(parts[1])
|
||||
assert major >= 3
|
||||
if major == 3:
|
||||
assert minor >= 2
|
||||
assert major >= 4
|
||||
|
||||
|
||||
# =============================================================================
|
||||
|
||||
Reference in New Issue
Block a user