Roman Zajic 34092b6efc
chore: Test waku fleet (#175)
* chore: build logos delivery lib locally

* test: soft attachment to waku.test

* chore: node1 node2 bootstrap from test fleet nodes
- selected test cases relay, store

* fix: cleanup artifacts after liblogosdelivery build

* chore: add fleet tests workflow

* fix: trigger on push and test

* fix: register markers

* test: add light_push to fleet tests

* test: add filter to fleet tests

* fix: add more store tests to fleet tests

* fix: add more relay to fleet tests

* fix: wf efficiency

* fix: wf syntax

* test: join fleet with real cluster ID shards RLN on

* fix: stop fleet tests when RLN registration fails

* fix: refactor monkeypatch

* fix: light_push tests

* fix: scoped assertion for store test in fleet mode

* fix: reduce comments

* fix: different propagation delay for fleet test

* fix: add fresh timestamp helper

* fix: reduce comments

* test: change to Waku v0.38.0 image temporarily

* fix: reduce log message

* fix: undo reduce log message

* fix: add scheduled run at 2 am.

* fix: fail fleet tests instead of skip when RLN is not working

* fix: refactor get_sample_timestamps

* fix: remove on push trigger for fleet wf
- reset back to use the latest docker image
2026-05-08 14:59:20 +08:00

380 lines
17 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
from time import time
from datetime import datetime, timedelta
NOW = datetime.now()
SAMPLE_INPUTS = [
{"description": "A simple string", "value": "Hello World!"},
{"description": "An integer", "value": "1234567890"},
{"description": "A dictionary", "value": '{"key": "value"}'},
{"description": "Chinese characters", "value": "这是一些中文"},
{"description": "Emojis", "value": "🚀🌟✨"},
{"description": "Lorem ipsum text", "value": "Lorem ipsum dolor sit amet"},
{"description": "HTML content", "value": "<html><body>Hello</body></html>"},
{"description": "Cyrillic characters", "value": "\u041f\u0440\u0438\u0432\u0435\u0442"},
{"description": "Base64 encoded string", "value": "Base64==dGVzdA=="},
{"description": "Binary data", "value": "d29ya2luZyB3aXRoIGJpbmFyeSBkYXRh: \x50\x51"},
{"description": "Special characters with whitespace", "value": "\t\nSpecial\tCharacters\n"},
{"description": "Boolean false as a string", "value": "False"},
{"description": "A float number", "value": "3.1415926535"},
{"description": "A list", "value": "[1, 2, 3, 4, 5]"},
{"description": "Hexadecimal number as a string", "value": "0xDEADBEEF"},
{"description": "Email format", "value": "user@example.com"},
{"description": "URL format", "value": "http://example.com"},
{"description": "Date and time in ISO format", "value": "2023-11-01T12:00:00Z"},
{"description": "String with escaped quotes", "value": '"Escaped" \\"quotes\\"'},
{"description": "A regular expression", "value": "Regular expression: ^[a-z0-9_-]{3,16}$"},
{"description": "A very long string", "value": "x" * 1000},
{"description": "A JSON string", "value": '{"name": "John", "age": 30, "city": "New York"}'},
{"description": "A Unix path", "value": "/usr/local/bin"},
{"description": "A Windows path", "value": "C:\\Windows\\System32"},
{"description": "An SQL query", "value": "SELECT * FROM users WHERE id = 1;"},
{"description": "JavaScript code snippet", "value": "function test() { console.log('Hello World'); }"},
{"description": "A CSS snippet", "value": "body { background-color: #fff; }"},
{"description": "A Python one-liner", "value": "print('Hello World')"},
{"description": "An IP address", "value": "192.168.1.1"},
{"description": "A domain name", "value": "www.example.com"},
{"description": "A user agent string", "value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"},
{"description": "A credit card number", "value": "1234-5678-9012-3456"},
{"description": "A phone number", "value": "+1234567890"},
{"description": "A UUID", "value": "123e4567-e89b-12d3-a456-426614174000"},
{"description": "A hashtag", "value": "#helloWorld"},
{"description": "A Twitter handle", "value": "@username"},
{"description": "A password", "value": "P@ssw0rd!"},
{"description": "A date in common format", "value": "01/11/2023"},
{"description": "A time string", "value": "12:00:00"},
{"description": "A mathematical equation", "value": "E = mc^2"},
]
INVALID_PAYLOADS = [
{"description": "Empty string", "value": ""},
{"description": "Unecoded text", "value": "Hello World!"},
{"description": "A dictionary", "value": {"key": "YWFh"}},
{"description": "An integer", "value": 1234567890},
{"description": "A list", "value": ["YWFh"]},
{"description": "A bool", "value": True},
]
INVALID_CONTENT_TOPICS = [
{"description": "Empty string", "value": ""},
{"description": "A dictionary", "value": {"key": "YWFh"}},
{"description": "An integer", "value": 1234567890},
{"description": "A list", "value": ["YWFh"]},
{"description": "A bool", "value": True},
]
CONTENT_TOPICS_DIFFERENT_SHARDS = [
"/myapp/1/latest/proto", # resolves to shard 0
"/waku/2/content/test.js", # resolves to shard 1
"/app/22/sometopic/someencoding", # resolves to shard 2
"/toychat/2/huilong/proto", # resolves to shard 3
"/statusim/1/community/cbor", # resolves to shard 4
"/app/27/sometopic/someencoding", # resolves to shard 5
"/app/29/sometopic/someencoding", # resolves to shard 6
"/app/20/sometopic/someencoding", # resolves to shard 7
]
CONTENT_TOPICS_SHARD_0 = [
"/newsService/1.0/weekly/protobuf",
"/newsService/1.0/alerts/xml",
"/newsService/1.0/updates/json",
"/newsService/2.0/alerts/json",
"/newsService/2.0/summaries/xml",
"/newsService/2.0/highlights/yaml",
"/newsService/3.0/weekly/json",
"/newsService/3.0/summaries/xml",
]
CONTENT_TOPICS_SHARD_7 = [
"/newsService/2.0/alerts/yaml",
"/newsService/2.0/highlights/xml",
"/newsService/3.0/daily/protobuf",
"/newsService/3.0/alerts/xml",
"/newsService/3.0/updates/protobuf",
"/newsService/3.0/reviews/xml",
"/newsService/4.0/alerts/yaml",
"/newsService/4.0/updates/yaml",
]
DEFAULT_CLUSTER_ID = "198"
VALID_PUBSUB_TOPICS = [
f"/waku/2/rs/{DEFAULT_CLUSTER_ID}/0",
f"/waku/2/rs/{DEFAULT_CLUSTER_ID}/1",
f"/waku/2/rs/{DEFAULT_CLUSTER_ID}/9",
f"/waku/2/rs/{DEFAULT_CLUSTER_ID}/25",
f"/waku/2/rs/{DEFAULT_CLUSTER_ID}/1000",
]
FLEET_CLUSTER_ID = "1"
FLEET_PUBSUB_TOPICS = [f"/waku/2/rs/{FLEET_CLUSTER_ID}/{i}" for i in range(8)]
PUBSUB_TOPICS_STORE = [
f"/waku/2/rs/{DEFAULT_CLUSTER_ID}/0",
f"/waku/2/rs/{DEFAULT_CLUSTER_ID}/1",
f"/waku/2/rs/{DEFAULT_CLUSTER_ID}/2",
f"/waku/2/rs/{DEFAULT_CLUSTER_ID}/3",
f"/waku/2/rs/{DEFAULT_CLUSTER_ID}/4",
f"/waku/2/rs/{DEFAULT_CLUSTER_ID}/5",
f"/waku/2/rs/{DEFAULT_CLUSTER_ID}/6",
f"/waku/2/rs/{DEFAULT_CLUSTER_ID}/7",
f"/waku/2/rs/{DEFAULT_CLUSTER_ID}/8",
]
INVALID_PUBSUB_TOPICS = ["/test/2/rs/0/1", "/waku/3/rs/0/1", "/waku/2/test/0/1", "/waku/2/rs/3/b", "/waku/2/rs/0"]
PUBSUB_TOPICS_DIFFERENT_CLUSTERS = [
"/waku/2/rs/2/0",
"/waku/2/rs/2/1",
"/waku/2/rs/5/0",
"/waku/2/rs/5/1",
"/waku/2/rs/5/999",
"/waku/2/rs/8/0",
"/waku/2/rs/999/999",
]
PUBSUB_TOPICS_SAME_CLUSTER = [
"/waku/2/rs/199/0",
"/waku/2/rs/199/1",
"/waku/2/rs/199/2",
"/waku/2/rs/199/3",
"/waku/2/rs/199/4",
"/waku/2/rs/199/5",
"/waku/2/rs/199/6",
"/waku/2/rs/199/7",
]
PUBSUB_TOPICS_WRONG_FORMAT = [
{"description": "A dictionary", "value": {"key": "YWFh"}},
{"description": "An integer", "value": 1234567890},
{"description": "A list", "value": ["YWFh"]},
{"description": "A bool", "value": True},
]
def get_sample_timestamps():
"""Return timestamp test-cases with values evaluated fresh at call time.
This factory function MUST be called from inside each test (never at module
import time) so that the "Now" value reflects the actual time when the
message is published.
Valid_for semantics:
``["nwaku"]`` accepted by nwaku in the current run mode.
``[]`` rejected by nwaku in the current run mode (either
structurally invalid type, or out-of-epoch in fleet/RLN
mode).
"""
now_ns = int(time() * 1e9)
now_dt = datetime.now()
fleet_mode = os.getenv("FLEET_BOOTSTRAP", "false").lower() == "true"
standalone_valid = [] if fleet_mode else ["nwaku"]
return [
{"description": "Now", "value": now_ns, "valid_for": ["nwaku"]},
# 10 years from now
{"description": "Far future", "value": int((now_dt + timedelta(days=365 * 10)).timestamp() * 1e9), "valid_for": standalone_valid},
# 1 hour ago
{"description": "Recent past", "value": int((now_dt - timedelta(hours=1)).timestamp() * 1e9), "valid_for": standalone_valid},
# 1 hour ahead
{"description": "Near future", "value": int((now_dt + timedelta(hours=1)).timestamp() * 1e9), "valid_for": standalone_valid},
{"description": "Positive number", "value": 1, "valid_for": standalone_valid},
{"description": "Negative number", "value": -1, "valid_for": standalone_valid},
# DST starts
{"description": "DST change", "value": int(datetime(2020, 3, 8, 2, 0, 0).timestamp() * 1e9), "valid_for": standalone_valid},
{"description": "Timestamp as string number", "value": str(now_ns), "valid_for": []},
{"description": "Invalid large number", "value": 2**63, "valid_for": []},
{"description": "Float number", "value": float(now_ns), "valid_for": []},
{"description": "Array instead of timestamp", "value": [now_ns], "valid_for": []},
{"description": "Object instead of timestamp", "value": {"time": now_ns}, "valid_for": []},
{"description": "ISO 8601 timestamp", "value": "2023-12-26T10:58:51", "valid_for": []},
{"description": "Missing", "value": None, "valid_for": []},
]
PUBSUB_TOPICS_RLN = [f"/waku/2/rs/{DEFAULT_CLUSTER_ID}/0"]
LOG_ERROR_KEYWORDS = [
"crash",
"fatal",
"panic",
"abort",
"segfault",
"corrupt",
"terminated",
"unhandled",
"stacktrace",
"deadlock",
"SIGSEGV",
"SIGABRT",
"stack overflow",
"index out of bounds",
"nil pointer dereference",
"goroutine exit",
"nil pointer",
"runtime error",
"goexit",
"race condition",
"double free",
]
METRICS_WITH_INITIAL_VALUE_ZERO = [
"libp2p_peers",
"libp2p_failed_upgrades_incoming_total",
"libp2p_failed_upgrades_outgoing_total",
"libp2p_total_dial_attempts_total",
"libp2p_successful_dials_total",
"libp2p_failed_dials_total",
"waku_rln_messages_total_total",
"waku_rln_spam_messages_total_total",
"waku_rln_proof_verification_total_total",
"waku_rln_number_registered_memberships",
"waku_rln_proof_verification_duration_seconds",
"waku_rln_proof_generation_duration_seconds",
"waku_rln_instance_creation_duration_seconds",
"waku_rln_membership_insertion_duration_seconds",
"waku_rln_membership_credentials_import_duration_seconds",
"waku_rln_remaining_proofs_per_epoch",
"waku_rln_total_generated_proofs",
"libp2p_pubsub_sig_verify_success_total",
"libp2p_pubsub_sig_verify_failure_total",
"libp2p_pubsub_disconnects_over_non_priority_queue_limit_total",
"libp2p_pubsub_peers",
"libp2p_pubsub_unsubscriptions_total",
"libp2p_pubsub_validation_success_total",
"libp2p_pubsub_validation_failure_total",
"libp2p_pubsub_validation_ignore_total",
"libp2p_pubsub_broadcast_iwant_total",
"libp2p_pubsub_received_iwant_total",
"libp2p_gossipsub_cache_window_size",
'libp2p_gossipsub_peers_per_topic_mesh{topic="other"}',
'libp2p_gossipsub_peers_per_topic_fanout{topic="other"}',
'libp2p_gossipsub_peers_per_topic_gossipsub{topic="other"}',
"libp2p_gossipsub_low_peers_topics",
"libp2p_gossipsub_healthy_peers_topics",
"libp2p_gossipsub_failed_publish_total",
"libp2p_gossipsub_invalid_topic_subscription_total",
"libp2p_gossipsub_duplicate_during_validation_total",
"libp2p_gossipsub_idontwant_saved_messages_total",
"libp2p_gossipsub_duplicate_total",
"libp2p_gossipsub_received_total",
"libp2p_rendezvous_register_total",
"libp2p_rendezvous_discover_total",
"libp2p_rendezvous_registered",
"libp2p_rendezvous_namespaces",
"waku_peer_store_size",
"waku_total_unique_peers",
"presto_server_missing_requests_count",
"presto_server_invalid_requests_count",
'waku_archive_messages{type="stored"}',
"waku_archive_insert_duration_seconds_sum",
"waku_archive_insert_duration_seconds_count",
'waku_archive_insert_duration_seconds_bucket{le="0.005"}',
'waku_archive_insert_duration_seconds_bucket{le="0.01"}',
'waku_archive_insert_duration_seconds_bucket{le="0.025"}',
'waku_archive_insert_duration_seconds_bucket{le="0.05"}',
'waku_archive_insert_duration_seconds_bucket{le="0.075"}',
'waku_archive_insert_duration_seconds_bucket{le="0.1"}',
'waku_archive_insert_duration_seconds_bucket{le="0.25"}',
'waku_archive_insert_duration_seconds_bucket{le="0.5"}',
'waku_archive_insert_duration_seconds_bucket{le="0.75"}',
'waku_archive_insert_duration_seconds_bucket{le="1.0"}',
'waku_archive_insert_duration_seconds_bucket{le="2.5"}',
'waku_archive_insert_duration_seconds_bucket{le="5.0"}',
'waku_archive_insert_duration_seconds_bucket{le="7.5"}',
'waku_archive_insert_duration_seconds_bucket{le="10.0"}',
'waku_archive_insert_duration_seconds_bucket{le="+Inf"}',
"waku_archive_query_duration_seconds_sum",
"waku_archive_query_duration_seconds_count",
'waku_archive_query_duration_seconds_bucket{le="0.005"}',
'waku_archive_query_duration_seconds_bucket{le="0.01"}',
'waku_archive_query_duration_seconds_bucket{le="0.025"}',
'waku_archive_query_duration_seconds_bucket{le="0.05"}',
'waku_archive_query_duration_seconds_bucket{le="0.075"}',
'waku_archive_query_duration_seconds_bucket{le="0.1"}',
'waku_archive_query_duration_seconds_bucket{le="0.25"}',
'waku_archive_query_duration_seconds_bucket{le="0.5"}',
'waku_archive_query_duration_seconds_bucket{le="0.75"}',
'waku_archive_query_duration_seconds_bucket{le="1.0"}',
'waku_archive_query_duration_seconds_bucket{le="2.5"}',
'waku_archive_query_duration_seconds_bucket{le="5.0"}',
'waku_archive_query_duration_seconds_bucket{le="7.5"}',
'waku_archive_query_duration_seconds_bucket{le="10.0"}',
'waku_archive_query_duration_seconds_bucket{le="+Inf"}',
"waku_filter_subscriptions",
"waku_filter_handle_message_duration_seconds_sum",
"waku_filter_handle_message_duration_seconds_count",
'waku_filter_handle_message_duration_seconds_bucket{le="0.005"}',
'waku_filter_handle_message_duration_seconds_bucket{le="0.01"}',
'waku_filter_handle_message_duration_seconds_bucket{le="0.025"}',
'waku_filter_handle_message_duration_seconds_bucket{le="0.05"}',
'waku_filter_handle_message_duration_seconds_bucket{le="0.075"}',
'waku_filter_handle_message_duration_seconds_bucket{le="0.1"}',
'waku_filter_handle_message_duration_seconds_bucket{le="0.25"}',
'waku_filter_handle_message_duration_seconds_bucket{le="0.5"}',
'waku_filter_handle_message_duration_seconds_bucket{le="0.75"}',
'waku_filter_handle_message_duration_seconds_bucket{le="1.0"}',
'waku_filter_handle_message_duration_seconds_bucket{le="2.5"}',
'waku_filter_handle_message_duration_seconds_bucket{le="5.0"}',
'waku_filter_handle_message_duration_seconds_bucket{le="7.5"}',
'waku_filter_handle_message_duration_seconds_bucket{le="10.0"}',
'waku_filter_handle_message_duration_seconds_bucket{le="+Inf"}',
"discovery_session_lru_cache_hits_total",
"discovery_session_lru_cache_misses_total",
"discovery_session_decrypt_failures_total",
"discovery_unsolicited_messages_total",
"discovery_enr_auto_update_total",
"waku_px_peers_received_total",
"waku_px_peers_received_unknown",
"waku_px_peers_sent_total",
"waku_px_peers",
"waku_histogram_message_size_sum",
"waku_histogram_message_size_count",
'waku_histogram_message_size_bucket{le="0.0"}',
'waku_histogram_message_size_bucket{le="1.0"}',
'waku_histogram_message_size_bucket{le="3.0"}',
'waku_histogram_message_size_bucket{le="5.0"}',
'waku_histogram_message_size_bucket{le="15.0"}',
'waku_histogram_message_size_bucket{le="50.0"}',
'waku_histogram_message_size_bucket{le="75.0"}',
'waku_histogram_message_size_bucket{le="100.0"}',
'waku_histogram_message_size_bucket{le="125.0"}',
'waku_histogram_message_size_bucket{le="150.0"}',
'waku_histogram_message_size_bucket{le="500.0"}',
'waku_histogram_message_size_bucket{le="700.0"}',
'waku_histogram_message_size_bucket{le="1000.0"}',
'waku_histogram_message_size_bucket{le="+Inf"}',
"waku_lightpush_peers",
"waku_filter_peers",
"waku_store_peers",
"waku_px_peers",
"waku_dnsdisc_discovered",
"rendezvousPeerFoundTotal_total",
"reconciliation_roundtrips_sum",
"reconciliation_roundtrips_count",
"reconciliation_differences_sum",
"reconciliation_differences_count",
'reconciliation_roundtrips_bucket{le="1.0"}',
'reconciliation_roundtrips_bucket{le="2.0"}',
'reconciliation_roundtrips_bucket{le="3.0"}',
'reconciliation_roundtrips_bucket{le="5.0"}',
'reconciliation_roundtrips_bucket{le="8.0"}',
'reconciliation_roundtrips_bucket{le="13.0"}',
'reconciliation_roundtrips_bucket{le="+Inf"}',
'reconciliation_differences_bucket{le="0.0"}',
'reconciliation_differences_bucket{le="10.0"}',
'reconciliation_differences_bucket{le="50.0"}',
'reconciliation_differences_bucket{le="100.0"}',
'reconciliation_differences_bucket{le="500.0"}',
'reconciliation_differences_bucket{le="1000.0"}',
'reconciliation_differences_bucket{le="5000.0"}',
'reconciliation_differences_bucket{le="+Inf"}',
'waku_filter_handle_message_duration_seconds_bucket{le="15.0"}',
'waku_filter_handle_message_duration_seconds_bucket{le="20.0"}',
'waku_filter_handle_message_duration_seconds_bucket{le="30.0"}',
"total_messages_cached",
"waku_store_queries_total",
"mix_pool_size",
"libp2p_gossipsub_imreceiving_saved_messages_total",
"postgres_payload_size_bytes",
]