Skip to content
Closed
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
8 changes: 2 additions & 6 deletions .github/workflows/test-integration-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ jobs:
with:
path: thinclient

- name: Checkout katzenpost repository
- name: Checkout katzenpost repository
uses: actions/checkout@v4
with:
repository: katzenpost/katzenpost
ref: rm_old_stuff
path: katzenpost

- name: Set up Docker Buildx
Expand Down Expand Up @@ -65,11 +66,6 @@ jobs:
cd thinclient
python -m pytest tests/ -vvv -s --tb=short

- name: Run Rust integration tests
run: |
cd thinclient
cargo test --test '*' -- --nocapture

- name: Stop the mixnet
if: always()
run: |
Expand Down
24 changes: 16 additions & 8 deletions katzenpost_thinclient/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -556,12 +556,13 @@ async def start(self, loop:asyncio.AbstractEventLoop) -> None:
assert response["connection_status_event"] is not None
await self.handle_response(response)

# 2nd message is always a new pki doc event
#response = await self.recv(loop)
#assert response is not None
#assert response["new_pki_document_event"] is not None, response
#await self.handle_response(response)

# 2nd message is always a new pki doc event (payload may be empty if mixnet is still booting)
response = await self.recv(loop)
if response is not None and response.get("new_pki_document_event") is not None:
await self.handle_response(response)
else:
self.logger.info("No PKI document event received during startup - will receive when available")

# Start the read loop as a background task
self.logger.debug("starting read loop")
self.task = loop.create_task(self.worker_loop(loop))
Expand Down Expand Up @@ -706,11 +707,18 @@ def pki_document(self) -> "Dict[str,Any] | None":
def parse_pki_doc(self, event: "Dict[str,Any]") -> None:
"""
Parse and store a new PKI document received from the daemon.

Handles the case where the daemon may not have a PKI document yet
(e.g., during initial connection before the network is fully available).
"""
self.logger.debug("parse pki doc")
assert event is not None
assert event["payload"] is not None
raw_pki_doc = cbor2.loads(event["payload"])
payload = event.get("payload")
# Handle empty payload - daemon may not have a PKI document yet
if payload is None or len(payload) == 0:
self.logger.info("No PKI document available yet - will receive when available")
return
raw_pki_doc = cbor2.loads(payload)
self.pki_doc = raw_pki_doc
self.logger.debug("parse pki doc success")

Expand Down
5 changes: 5 additions & 0 deletions tests/channel_api_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ async fn setup_thin_client() -> Result<std::sync::Arc<ThinClient>, Box<dyn std::
/// This test demonstrates the full channel workflow: Alice creates a write channel,
/// Bob creates a read channel, Alice writes messages, Bob reads them back.
#[tokio::test]
#[ignore = "Channel API tests temporarily disabled"]
async fn test_channel_api_basics() -> Result<(), Box<dyn std::error::Error>> {
let alice_thin_client = setup_thin_client().await?;
let bob_thin_client = setup_thin_client().await?;
Expand Down Expand Up @@ -177,6 +178,7 @@ async fn test_channel_api_basics() -> Result<(), Box<dyn std::error::Error>> {
/// 7. Read first and second message from the channel
/// 8. Verify payloads match
#[tokio::test]
#[ignore = "Channel API tests temporarily disabled"]
async fn test_resume_write_channel() -> Result<(), Box<dyn std::error::Error>> {
let alice_thin_client = setup_thin_client().await?;
let bob_thin_client = setup_thin_client().await?;
Expand Down Expand Up @@ -341,6 +343,7 @@ async fn test_resume_write_channel() -> Result<(), Box<dyn std::error::Error>> {
/// 8. Read both messages from channel
/// 9. Verify payloads match
#[tokio::test]
#[ignore = "Channel API tests temporarily disabled"]
async fn test_resume_write_channel_query() -> Result<(), Box<dyn std::error::Error>> {
let alice_thin_client = setup_thin_client().await?;
let bob_thin_client = setup_thin_client().await?;
Expand Down Expand Up @@ -504,6 +507,7 @@ async fn test_resume_write_channel_query() -> Result<(), Box<dyn std::error::Err
/// 8. Read the second message from the channel
/// 9. Verify payload matches
#[tokio::test]
#[ignore = "Channel API tests temporarily disabled"]
async fn test_resume_read_channel() -> Result<(), Box<dyn std::error::Error>> {
let alice_thin_client = setup_thin_client().await?;
let bob_thin_client = setup_thin_client().await?;
Expand Down Expand Up @@ -666,6 +670,7 @@ async fn test_resume_read_channel() -> Result<(), Box<dyn std::error::Error>> {
/// 9. Read second message from channel
/// 10. Verify received payload matches
#[tokio::test]
#[ignore = "Channel API tests temporarily disabled"]
async fn test_resume_read_channel_query() -> Result<(), Box<dyn std::error::Error>> {
let alice_thin_client = setup_thin_client().await?;
let bob_thin_client = setup_thin_client().await?;
Expand Down
2 changes: 2 additions & 0 deletions tests/test_channel_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ async def setup_thin_client():
return client


@pytest.mark.skip(reason="Channel API tests temporarily disabled")
@pytest.mark.asyncio
async def test_channel_api_basics():
"""
Expand Down Expand Up @@ -176,6 +177,7 @@ async def test_channel_api_basics():
print("✅ Channel API basics test completed successfully")


@pytest.mark.skip(reason="Channel API tests temporarily disabled")
@pytest.mark.asyncio
async def test_resume_write_channel():
"""
Expand Down
3 changes: 3 additions & 0 deletions tests/test_channel_api_extended.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ async def setup_thin_client():
return client


@pytest.mark.skip(reason="Channel API tests temporarily disabled")
@pytest.mark.asyncio
async def test_resume_write_channel_query():
"""
Expand Down Expand Up @@ -180,6 +181,7 @@ async def test_resume_write_channel_query():
print("✅ Resume write channel query test completed successfully")


@pytest.mark.skip(reason="Channel API tests temporarily disabled")
@pytest.mark.asyncio
async def test_resume_read_channel():
"""
Expand Down Expand Up @@ -334,6 +336,7 @@ async def test_resume_read_channel():
print("✅ Resume read channel test completed successfully")


@pytest.mark.skip(reason="Channel API tests temporarily disabled")
@pytest.mark.asyncio
async def test_resume_read_channel_query():
"""
Expand Down
13 changes: 10 additions & 3 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ async def test_thin_client_send_receive_integration_test():
"""Test basic send/receive functionality with the echo service."""
from .conftest import is_daemon_available

# Skip test if daemon is not available
if not is_daemon_available():
pytest.skip("Katzenpost client daemon not available")
# Fail test if daemon is not available
assert is_daemon_available(), "Katzenpost client daemon not available"
from .conftest import get_config_path

config_path= get_config_path()
Expand All @@ -37,6 +36,14 @@ async def test_thin_client_send_receive_integration_test():
try:
await client.start(loop)

# Wait for PKI document to be available (received asynchronously)
attempts = 0
while client.pki_document() is None and attempts < 30:
await asyncio.sleep(1)
attempts += 1

assert client.pki_document() is not None, "PKI document not received within 30 seconds"

service_desc = client.get_service("echo")
surb_id = client.new_surb_id()
payload = "hello"
Expand Down
Loading