Skip to content

Latest commit

 

History

History
826 lines (779 loc) · 29.8 KB

File metadata and controls

826 lines (779 loc) · 29.8 KB

Test Inventory

Generated by make test-inventory (tests/inventory.sh). Do not edit by hand — re-run the target to refresh. See Testing Strategy for how the tiers fit together.

Totals: 511 dashboard unit tests · 12 contract tests · 31 frontend tests · 46 pithead shell sections · 17 harness self-test sections · 9 live config scenarios (17 axis values) · 6 mini-stack scenarios.

Counts are test functions / named cases (parametrized pytest cases expand to more at run time — e.g. the dashboard suite collects ~381). Generated statically by grep, so it's stable regardless of what's installed.

Tier Suite Cases
1 — Unit dashboard pytest 511
1 — Unit frontend (node --test) 31
1 — Unit pithead shell suite 46 sections
1 — Unit compose interpolation + hardening (#90) 1
2 — Contract fake-daemon clients 12
3 — Mini-stack docker control-plane scenarios 6
4 — Live matrix config scenarios 9 (17 axis values)
4 — Live matrix harness self-test 17 sections

Tier 1 — Unit & component

Dashboard (pytest) — 511 tests

tests/client/test_docker_control.py — 6

  • test_tcp_scheme_rewritten_to_http
  • test_stop_success_204
  • test_already_stopped_304_is_success
  • test_start_success
  • test_error_status_returns_false
  • test_connection_error_returns_false

tests/client/test_monero_client.py — 12

  • test_url_and_digest_auth_built
  • test_no_username_means_no_auth
  • test_success_returns_payload
  • test_network_error_returns_none
  • test_non_200_returns_none
  • test_non_json_returns_none
  • test_busy_status_returns_none
  • test_syncing
  • test_synced_via_flag
  • test_synced_via_zero_target
  • test_synced_when_height_reaches_target
  • test_unreachable_returns_none

tests/client/test_tari_client.py — 7

  • test_fully_synced
  • test_syncing_with_target
  • test_syncing_without_reliable_target
  • test_grpc_error_returns_default_when_no_cache
  • test_serves_last_known_state_on_transient_failure
  • test_stale_cache_expires
  • test_close_closes_channel

tests/client/test_xmrig_client.py — 7

  • test_first_success_returns_payload_and_short_circuits
  • test_all_attempts_fail_returns_empty
  • test_exceptions_are_swallowed
  • test_ssrf_targets_are_never_probed
  • test_real_miner_ip_is_probed
  • test_name_is_used_as_bearer_never_as_host
  • test_long_name_token_is_capped

tests/client/test_xmrig_proxy_client.py — 7

  • test_auth_header_set
  • test_get_summary
  • test_get_workers
  • test_get_config
  • test_update_config_returns_json
  • test_update_config_204_returns_empty
  • test_get_summary_raises_on_http_error

tests/client/test_xvb_client.py — 9

  • test_missing_wallet_returns_none
  • test_get_stats_success_parses_html
  • test_get_stats_routes_through_tor_proxy
  • test_get_stats_honours_explicit_proxy
  • test_get_stats_non_200_returns_none
  • test_get_stats_network_error_returns_none
  • test_fail_count_only
  • test_no_critical_stats_returns_none
  • test_hashrate_units

tests/collector/test_logs.py — 18

  • test_parses_multiple_frames
  • test_skips_blank_lines
  • test_truncated_frame_breaks_cleanly
  • test_success
  • test_non_200_returns_error
  • test_connection_error_handled
  • test_syncing
  • test_synced
  • test_file_not_found
  • test_bad_json
  • test_new_format_top_block_candidate
  • test_old_synced_format
  • test_already_synchronized
  • test_error_logs
  • test_rpc_result_used_when_available
  • test_falls_back_to_logs_when_rpc_unreachable
  • test_local_when_default_host
  • test_remote_when_other_host

tests/collector/test_pools.py — 15

  • test_empty_is_unknown
  • test_majority_wins
  • test_unknown_ports
  • test_port_matched_exactly_not_as_substring
  • test_aggregates_sources
  • test_empty_files_give_defaults
  • test_hashrate_derived_when_missing
  • test_hashrate_passthrough
  • test_worker_parsing
  • test_worker_without_name_defaults_to_miner
  • test_active_chain_converts_utari
  • test_no_chains_inactive
  • test_missing_file_returns_empty
  • test_malformed_json_returns_empty
  • test_valid_json

tests/collector/test_system.py — 11

  • test_normal
  • test_error_returns_zeros
  • test_parses_meminfo
  • test_error_returns_zeros
  • test_formats
  • test_error
  • test_delta_calculation
  • test_malformed_line
  • test_enabled_when_used
  • test_allocated_when_unused
  • test_unknown_when_missing

tests/config/test_config.py — 8

  • test_defaults_load
  • test_donation_level_env_override
  • test_monero_prune_accepts_truthy_forms
  • test_monero_prune_accepts_falsy_forms
  • test_update_interval_tolerates_bad_values
  • test_tier_config_env_override_valid
  • test_tier_config_env_override_invalid_json_falls_back
  • test_xvb_enabled_flag

tests/helper/test_utils.py — 29

  • test_plain_numbers
  • test_unit_suffixes_case_insensitive
  • test_unrecognized_suffix_is_raw
  • test_bad_data_returns_zero
  • test_unit_boundaries
  • test_bad_data
  • test_branches
  • test_bad_data
  • test_formats_localtime
  • test_falsy_is_never
  • test_invalid_type_does_not_crash
  • test_default_tiers
  • test_custom_tiers
  • test_zero_threshold_ignored
  • test_auto_picks_highest_sustainable
  • test_auto_zero_when_nothing_sustainable
  • test_named_tier_honored
  • test_named_tier_not_downgraded_but_flagged_unsustainable
  • test_cannot_sustain_named_tier_is_flagged
  • test_numeric_level_honored
  • test_unknown_level_falls_back_to_lowest
  • test_ipv4_is_an_address
  • test_ipv6_is_an_address
  • test_hostname_is_not_an_address
  • test_surrounding_whitespace_tolerated
  • test_non_string_and_empty_are_not_addresses
  • test_returns_socket_source_address
  • test_none_when_no_route
  • test_socket_is_closed_even_on_error

tests/service/test_algo_service.py — 31

  • test_xvb_disabled_forces_p2pool
  • test_zero_shares_forces_p2pool
  • test_excessive_failures_forces_p2pool
  • test_low_hashrate_no_tier_is_p2pool
  • test_cold_start_seeds_feedforward
  • test_loop_ramps_up_when_below_reference
  • test_loop_backs_off_when_above_reference
  • test_advance_false_does_not_move_the_loop
  • test_nano_pool_uses_longer_window
  • test_difficulty_reserve_caps_donation
  • test_falls_back_to_flat_cap_without_difficulty
  • test_reserve_never_exceeds_hard_cap
  • test_loop_clamped_to_reserve
  • test_reference_cushion_is_absolute_capped
  • test_fraction_to_ms_zero_and_positive
  • test_advance_noop_when_no_hashrate
  • test_advance_clamps_to_bounds
  • test_routed_fraction_for_instrumentation
  • test_get_target_uses_state_manager_tiers
  • test_default_auto_targets_highest_sustainable
  • test_explicit_tier_not_downgraded
  • test_switch_updates_proxy_and_state
  • test_switch_aborts_on_bad_config
  • test_xvb_pool_routed_over_tor_by_default
  • test_local_pool_never_routed_over_tor
  • test_xvb_tor_opt_out_no_socks5
  • test_aborts_early_when_decision_flips_to_donate
  • test_aborts_early_when_below_tier
  • test_sleeps_full_duration_when_in_tier_on_p2pool
  • test_run_invokes_switch_then_stops
  • test_run_skips_switching_while_workers_rejected

tests/service/test_clearnet_sync.py — 11

  • test_flag_off_is_noop
  • test_syncing_reports_exposed_without_acting
  • test_synced_writes_marker_and_restarts_onto_tor
  • test_marker_written_before_restart
  • test_already_transitioned_is_idempotent
  • test_preexisting_marker_never_touches_container
  • test_failed_restart_retries_next_cycle
  • test_slow_stop_does_not_skip_start
  • test_restart_stop_timeout_outlasts_kill_deadline
  • test_per_chain_independent
  • test_marker_write_failure_does_not_restart

tests/service/test_data_service.py — 68

  • test_first_poll_baselines_without_backfill
  • test_delta_records_the_difference
  • test_no_change_records_nothing
  • test_counter_reset_rebaselines
  • test_parse_list_row_named_fields
  • test_parse_list_row_share_counts
  • test_parse_list_row_offline_and_uptime
  • test_parse_legacy_dict_row
  • test_parse_legacy_dict_share_counts
  • test_list_format_online
  • test_list_format_offline_when_no_connections
  • test_list_format_uptime_starts_at_zero
  • test_short_list_row_is_skipped
  • test_legacy_dict_format
  • test_legacy_dict_defaults
  • test_missing_payload_returns_empty
  • test_extracts_results_and_best
  • test_best_defaults_to_zero_when_empty
  • test_missing_results_block_zeros_out
  • test_malformed_payload_returns_empty
  • test_valid_summary_is_adopted
  • test_malformed_payload_keeps_last_good
  • test_valid_zero_summary_is_adopted_not_treated_as_malformed
  • test_online_uptime_counts_from_first_seen
  • test_real_api_uptime_is_not_overwritten
  • test_offline_worker_shown_until_falloff_then_dropped
  • test_fallen_off_worker_stays_gone_while_proxy_keeps_reporting_it
  • test_reconnect_restarts_uptime_and_readds
  • test_offline_then_online_resets_connected_since
  • test_proxy_kind_scales_khs_to_hs
  • test_xmrig_kind_not_scaled
  • test_unreachable_direct_api_keeps_proxy_values_online
  • test_short_hashrate_total_ignored
  • test_prefers_h15
  • test_falls_back_to_h60_then_h10
  • test_offline_excluded
  • test_empty
  • test_sums_each_window_independently
  • test_no_fallback_between_windows
  • test_offline_excluded_and_missing_keys_zero
  • test_empty
  • test_restores_snapshot
  • test_ignores_non_dict_snapshot
  • test_restores_workers_rejected_flag
  • test_restores_miner_released_latch
  • test_holds_miner_when_restart_mid_sync
  • test_stop_when_monero_down
  • test_stop_when_tari_down_and_required
  • test_tari_down_ignored_when_non_blocking
  • test_stop_failure_keeps_flag_false_for_retry
  • test_no_double_stop_when_already_rejected
  • test_readmit_when_relevant_nodes_healthy
  • test_no_readmit_while_a_relevant_node_unconfirmed
  • test_readmit_ignores_tari_when_non_blocking
  • test_no_readmit_until_monero_healthy_even_if_tari_non_blocking
  • test_holds_all_containers_when_not_synced
  • test_releases_when_gate_satisfied
  • test_noop_once_released
  • test_partial_start_failure_keeps_latch_closed
  • test_rehold_stops_quietly_after_first_cycle
  • test_single_iteration_aggregates
  • test_run_holds_miner_while_syncing
  • test_run_releases_despite_height_override
  • test_run_nonblocking_tari_releases_and_stays_operational
  • test_iteration_survives_collector_error
  • test_run_holds_when_tari_required_and_only_monero_synced
  • test_post_release_blip_lets_failover_act_without_rehold
  • test_both_nodes_down_rejects_once

tests/service/test_earnings.py — 4

  • test_matches_closed_form
  • test_worked_field_example
  • test_linear_in_inputs
  • test_missing_or_bad_inputs_are_zero

tests/service/test_metrics.py — 40

  • test_empty_history_returns_zero
  • test_averages_v_p2pool_in_window
  • test_excludes_samples_outside_window
  • test_legacy_rows_count_as_p2pool
  • test_xvb_samples_drag_average_down
  • test_empty_history_returns_zero
  • test_averages_v_xvb_in_window
  • test_excludes_samples_outside_window
  • test_legacy_rows_read_xvb_zero
  • test_complements_p2pool_to_total
  • test_total_and_stratum_passthrough
  • test_p2pool_averages_from_history
  • test_xvb_credited_averages_from_stats
  • test_xvb_routed_averages_from_history
  • test_xvb_routed_zero_without_history
  • test_mode_default
  • test_xvb_disabled_overrides_mode_and_tiers
  • test_current_tier_from_min_1h_24h
  • test_current_tier_uses_lower_of_1h_24h_on_drop
  • test_low_hr_warning_for_unsustainable_explicit_tier
  • test_no_warning_for_auto
  • test_no_warning_when_sustainable
  • test_fail_count_and_last_update
  • test_counts_online_and_total
  • test_empty
  • test_counts_recent_within_pplns_window
  • test_nano_block_time
  • test_loading_when_no_target
  • test_done_when_full
  • test_mid_sync_remaining
  • test_down_flag
  • test_global_syncing
  • test_local_pruned
  • test_local_full
  • test_remote_unknown
  • test_pool_and_network_figures
  • test_tari_mining_flag
  • test_empty_snapshot_does_not_crash
  • test_history_fetched_when_not_passed
  • test_passed_history_avoids_refetch

tests/service/test_node_health.py — 6

  • test_not_down_before_threshold
  • test_down_after_threshold
  • test_single_blip_does_not_trip
  • test_never_reachable_never_down
  • test_down_clears_only_after_recovery_window
  • test_healthy_requires_stable_window_from_unknown

tests/service/test_numeric_properties.py — 10

  • test_xmr_per_hs_day_non_negative
  • test_xmr_per_hs_day_zero_on_nonpositive_reward
  • test_xmr_per_hs_day_linear_in_reward
  • test_xmr_per_hs_day_decreases_with_difficulty
  • test_window_avgs_non_negative_and_conserve
  • test_window_avgs_empty_history_is_zero
  • test_fraction_to_ms_monotone_and_non_negative
  • test_fraction_to_ms_zero_on_nonpositive
  • test_routed_fraction_in_unit_interval
  • test_max_donation_fraction_within_reserve_bounds

tests/service/test_storage_service.py — 30

  • test_get_tiers
  • test_default_xvb_stats
  • test_partial_updates
  • test_kwargs_update_and_type_coercion
  • test_none_kwargs_skipped
  • test_unknown_kwarg_ignored
  • test_real_fetch_sets_last_update
  • test_local_only_writes_do_not_set_last_update
  • test_add_share_and_dedup
  • test_add_shares_records_count_distinct
  • test_add_shares_count_zero_or_one
  • test_old_shares_pruned_from_memory
  • test_update_history_roundtrip
  • test_history_bad_values_default_zero
  • test_per_window_splits_persisted
  • test_per_window_splits_survive_reload
  • test_healthy_by_default
  • test_unhealthy_after_write_error
  • test_roundtrip
  • test_empty_snapshot_not_saved
  • test_load_missing_snapshot_returns_none
  • test_share_stats_persist_across_instances
  • test_state_persists_across_instances
  • test_legacy_kv_keys_migrated_on_load
  • test_corrupted_kv_value_skipped
  • test_history_timestamp_backfilled_from_iso_on_upgrade
  • test_per_window_columns_added_on_upgrade
  • test_orphaned_workers_table_dropped_on_upgrade
  • test_history_older_than_retention_pruned_from_memory
  • test_old_history_pruned_from_db_when_cleanup_fires

tests/service/test_update_checker.py — 16

  • test_accepts_plain_and_v_prefixed
  • test_ignores_prerelease_and_build_suffix
  • test_rejects_garbage_partial_and_empty
  • test_newer_returns_payload
  • test_equal_or_older_returns_none
  • test_unparseable_either_side_returns_none
  • test_major_and_minor_ordering
  • test_parses_tag_and_url
  • test_non_200_is_silent_none
  • test_network_error_is_silent_none
  • test_missing_fields_is_none
  • test_disabled_never_calls_and_returns_none
  • test_enabled_flags_a_newer_release
  • test_throttles_to_interval
  • test_failed_fetch_keeps_previous_result
  • test_up_to_date_yields_none

tests/sim/test_donation_model.py — 10

  • test_holds_tier_without_overshoot
  • test_no_windup_from_cold_start
  • test_more_headroom_means_more_p2pool
  • test_holds_tier_across_credit_factor
  • test_overcredit_frees_p2pool
  • test_stable_under_lag
  • test_reserve_keeps_p2pool_in_the_window
  • test_low_tier_high_difficulty_caps_donation_for_vip
  • test_zero_reads_do_not_run_away
  • test_recovers_after_worker_drop

tests/sim/test_donation_model_properties.py — 1

  • test_controller_never_winds_up

tests/test_main.py — 1

  • test_build_app_returns_wired_application

tests/test_version.py — 11

  • test_version_with_no_git_metadata_is_a_release
  • test_leading_v_in_version_is_not_doubled
  • test_explicit_release_flag_wins_over_git_metadata
  • test_release_flag_accepts_common_truthy_spellings
  • test_branch_and_commit
  • test_commit_only
  • test_branch_only
  • test_dirty_marker_passes_through
  • test_a_versioned_build_with_a_commit_is_still_dev
  • test_no_metadata_falls_back_to_generic_dev
  • test_blank_values_treated_as_absent

tests/web/test_server.py — 23

  • test_index_serves_shell
  • test_get_state_ok_json
  • test_range_query_accepted
  • test_from_to_window_accepted
  • test_malformed_from_to_falls_back
  • test_window_filters_history_end_to_end
  • test_node_down_badges_in_state
  • test_passive_tari_badge_in_state
  • test_state_error_is_sanitized_json
  • test_security_headers_present
  • test_csp_has_no_unsafe_inline_or_eval
  • test_state_response_also_carries_headers
  • test_apply_security_headers_unit
  • test_js_mimetypes_registered
  • test_frontend_modules_served
  • test_static_assets_revalidate
  • test_shell_revalidates
  • test_css_has_phone_breakpoint
  • test_css_has_horizontal_scroll_rule
  • test_workers_table_opts_into_scroll_wrapper
  • test_css_lets_stat_values_wrap
  • test_css_lets_hostname_wrap
  • test_host_at_separator_styled_and_rendered

tests/web/test_views.py — 120

  • test_point_shape_is_xy_with_epoch_ms
  • test_legacy_rows_attributed_to_p2pool
  • test_range_filtering
  • test_downsampling_caps_points
  • test_outage_inserts_null_break
  • test_regular_data_has_no_breaks
  • test_single_missing_sample_does_not_break
  • test_break_sits_inside_the_gap
  • test_threshold_adapts_to_spacing
  • test_downsampled_outage_still_breaks
  • test_single_point_no_break
  • test_share_points_sparse_and_top_pinned
  • test_share_marker_top_pinned_when_value_zero
  • test_no_shares_no_points
  • test_unknown_range_keeps_everything
  • test_empty_history
  • test_custom_window_filters_both_bounds
  • test_window_overrides_range
  • test_short_window_kept_at_native_resolution
  • test_long_window_downsamples_to_tier
  • test_target_points_tiers
  • test_chart_tension_tiers
  • test_stacked_series_sum_to_the_total
  • test_zoom_reveals_more_detail
  • test_all_range_adapts_density_to_data_extent
  • test_default_window_is_10m
  • test_each_window_selects_its_columns
  • test_legacy_fallback_only_on_default_window
  • test_canonical_window_validates
  • test_downsample_preserves_per_window_columns
  • test_wide_range_keeps_nondefault_avg_nonzero
  • test_build_state_echoes_selected_window
  • test_build_state_defaults_to_10m
  • test_formats_hashrates
  • test_routed_distinct_from_credited
  • test_p2pool_mode_grays_xvb
  • test_xvb_mode_grays_p2pool
  • test_split_mode_both_active
  • test_low_hr_badge_present_only_when_warned
  • test_tiers_and_fail_count_passthrough
  • test_loading_done_syncing_states
  • test_done_state
  • test_synced_node_with_no_target_shows_done
  • test_no_target_but_not_caught_up_is_not_done
  • test_monero_mode_and_db_passthrough
  • test_syncing_shows_syncing_only
  • test_operational_shows_mode_and_pool
  • test_low_hr_badge
  • test_no_share_badge_when_donating_without_a_share
  • test_no_share_badge_absent_when_has_share_or_xvb_off
  • test_node_down_and_rejected
  • test_miner_held
  • test_passive_tari_with_and_without_percent
  • test_monero_pruned_badge
  • test_monero_full_badge
  • test_no_prune_badge_when_unknown
  • test_disk_badge_critical
  • test_disk_badge_warn
  • test_no_disk_badge_when_ample
  • test_no_disk_badge_when_missing
  • test_high_usage_levels_and_fill
  • test_warning_fill_between_70_and_90
  • test_unparseable_cpu_is_ok
  • test_empty_system_defaults
  • test_pool_tokens
  • test_formatted_and_raw_fields
  • test_online_sorted_before_offline
  • test_malformed_worker_skipped
  • test_bad_ip_sorts_to_zero
  • test_name_passthrough
  • test_share_counts_raw_and_formatted
  • test_invalid_appended_to_rejected_string_only_when_nonzero
  • test_missing_share_fields_default_to_zero
  • test_reject_flag_set_on_high_reject_rate
  • test_none_without_rejects
  • test_none_below_noise_floor
  • test_none_when_rate_low
  • test_flags_high_rate_above_floor
  • test_flags_all_rejects_at_floor
  • test_active
  • test_inactive_defaults
  • test_long_wallet_shortened
  • test_formats_totals_and_best
  • test_reject_pct_and_level
  • test_best_dash_when_unknown
  • test_empty_summary_has_no_data
  • test_formats_from_metrics_and_data
  • test_db_size_dash_when_unknown
  • test_resolves_ip_for_a_hostname
  • test_none_when_host_is_already_an_ip
  • test_none_when_ip_undetectable
  • test_none_when_detected_ip_equals_host
  • test_publishes_rate_and_inputs
  • test_default_hashrate_is_the_displayed_p2pool_1h
  • test_no_p2pool_hashrate_when_average_is_zero
  • test_unavailable_when_network_reward_missing
  • test_unavailable_when_difficulty_missing
  • test_p2pool_hr_passthrough_is_raw
  • test_has_all_sections
  • test_version_section_shape
  • test_update_section_surfaced_and_defaults_none
  • test_is_json_serializable
  • test_db_unhealthy_surfaces_field_and_badge
  • test_db_healthy_no_badge
  • test_range_echoed
  • test_window_null_on_preset
  • test_window_echoed_when_zoomed
  • test_syncing_flag_and_title
  • test_proxy_workers_from_metrics
  • test_chart_uses_timestamps
  • test_propagates_state_errors
  • test_valid_pair
  • test_absent_is_none
  • test_malformed_falls_back_to_none
  • test_returns_html_referencing_module
  • test_error_fallback
  • test_yes_when_in_tier_and_has_share
  • test_no_when_below_tier_even_with_a_share
  • test_no_when_in_tier_but_no_share
  • test_na_when_xvb_off

Frontend logic (node --test) — 31 tests

  • sortWorkers: null index keeps the server-provided order
  • sortWorkers: numeric columns sort numerically, not lexically
  • sortWorkers: hashrate column also sorts numerically
  • sortWorkers: descending reverses the order
  • sortWorkers: name column sorts as text
  • sortWorkers: does not mutate the input array
  • WORKER_COLUMNS: keys match the worker fields the server sends
  • sortWorkers: rejected column sorts numerically (find problem rigs)
  • fmtTimestamp: returns a non-empty string for an epoch-ms value
  • normalizeTheme: passes valid modes through, defaults the rest to auto
  • THEME_ORDER: the control renders every theme exactly once
  • normalizeAvgWindow: passes valid windows through, defaults the rest to 10m (#168)
  • AVG_WINDOWS: the client window set matches the server contract (#168)
  • clampZoomWindow: orders endpoints and enforces a minimum span
  • clampZoomWindow: rejects unusable input
  • fmtWindowDuration: two coarsest units, trailing zeros dropped
  • normalizeSeries: defaults every series to visible, only explicit false hides
  • parseHashrate: accepts bare numbers and k/M/G suffixes
  • parseHashrate: rejects empty / unparseable input
  • computeEarnings: scales the daily rate to day/month/year + time-to-share
  • computeEarnings: returns nulls when unavailable or hashrate is non-positive
  • computeEarnings: no time-to-share when share difficulty is unknown
  • heroKpis: surfaces the six headline numbers under stable labels, in order
  • heroKpis: wires each KPI to its build_state field
  • heroKpis: shares colour reflects the ok flag
  • heroKpis: Raffle Eligible colour reflects win eligibility (#158)
  • raffleCls: muted when XvB off (N/A), green when eligible, red otherwise (#158)
  • heroKpis: mode colour follows the server mode_variant token
  • heroKpis: total is accent-coloured; blocks and tier carry no colour class
  • bandBorderWidth: zero-height segments get no border, real ones keep full width
  • uptimeCell: online shows uptime, offline shows DOWN

pithead shell suite (tests/stack/run.sh) — 46 sections

  • unit: resolve_default
  • unit: assert_safe_dir
  • unit: is_public_ip classifier (#113)
  • unit: is_ipv4
  • unit: resolve_dashboard_host (dashboard.host 'auto' revert, 247c5a0)
  • unit: docker_boot_enabled (#137)
  • unit: is_valid_host (#130)
  • unit: describe_change
  • unit: p2pool_outbound_flags — Tor-by-default for outbound P2P (#165)
  • p2pool entrypoint word-splits P2POOL_FLAGS into separate args (#165)
  • unit: tor_egress_rules — fail-closed Tor-only egress ruleset (#270)
  • black-box: apply/remove_tor_egress_firewall via stubbed iptables (#270)
  • unit: clearnet initial sync helpers (#183)
  • unit: clock_sync_status (mining is time-sensitive)
  • unit: monero_address_type — p2pool needs a PRIMARY address (#250)
  • unit: dashboard auth (#8)
  • unit: generate_caddyfile scheme (#140)
  • unit: host detection (#140)
  • unit: release.sh pure logic (#44)
  • unit: pull-vs-build mode (#44)
  • unit: explain_subnet_collision (#180)
  • unit: env helpers
  • unit: export_build_provenance (Issue #58)
  • unit: node credential helpers
  • unit: randomx_boot_params (#176)
  • unit: grub heal + boot-param insert (#176)
  • unit: disk_component_gib
  • unit: check_disk_grouped (mocked df)
  • node configs: no clearnet DNS egress (#161 monerod, #162 tari)
  • black-box: CLI dispatch
  • black-box: guards
  • black-box: config validation
  • black-box: dashboard auth lifecycle (#8)
  • black-box: apply preserves secrets + propagates
  • black-box: xmrig-proxy knobs (#152 stratum auth, #173 donate-level)
  • black-box: clearnet initial sync render (#183)
  • black-box: local node creds auto-generated + persisted (#50)
  • black-box: upgrade re-renders generated config (#128)
  • black-box: apply recovers from a failed 'compose up' (#125)
  • black-box: up warns about missing (relocated) data dirs (#126)
  • black-box: status health check
  • black-box: doctor exit code (#127)
  • black-box: backup -> restore round-trip (#140)
  • black-box: reset-dashboard targets .env dirs, not config.json (#139)
  • black-box: reset-dashboard refuses to guess without .env dirs (#139)
  • release: install bundle is free of macOS xattr pax headers (#252)

Compose validation + hardening (tests/stack/test_compose.sh)

  • docker-compose.yml ${VAR} interpolation resolves against a representative .env
  • #90 hardening invariants: no-new-privileges / cap_drop / read-only roots, credential-free healthchecks, least-privilege Docker socket proxies, and the pinned pithead project name

Tier 2 — Contract (real clients vs controllable fakes)

tests/integration/fakes/test_contract.py — 12 tests

  • test_monero_synced_reads_no_sync_and_db_size
  • test_monero_syncing_reports_percent
  • test_monero_down_is_unreachable
  • test_monero_busy_status_is_unreachable
  • test_monero_synced_by_height_even_without_flag
  • test_monero_db_size_unknown_reads_zero
  • test_monero_http_control_mutates_state
  • test_tari_synced_reads_done
  • test_tari_syncing_reports_percent
  • test_tari_down_is_unreachable_with_no_cache
  • test_tari_syncing_without_reliable_target_avoids_false_100
  • test_tari_serves_cached_reading_when_briefly_unreachable

Tier 3 — Fake-daemon mini-stack (docker)

tests/integration/mini-stack/run-mini-stack.sh — 6 scenarios

  • scenario 1: holds the miner while both chains sync
  • scenario 2: keeps holding while Tari (required) is still syncing
  • scenario 3: releases the miner once both chains are synced
  • scenario 4: rejects workers when required Tari is down
  • scenario 5: readmits workers when Tari recovers
  • scenario 6: a dashboard restart does not re-hold a released miner

Tier 4 — Live config matrix (real synced server)

Config scenarios (tests/integration/scenarios.sh) — 9

  • local-pruned-main-secure-tari
  • local-full-main-secure-tari
  • local-pruned-mini-secure-tari
  • local-pruned-nano-insecure
  • local-pruned-main-rpclan
  • local-pruned-main-xvb-off
  • local-pruned-main-tari-optional
  • local-pruned-main-clearnet-sync
  • remote-main-secure-tari

Axis coverage (every value exercised at least once) — 17

  • monero.mode=local
  • monero.mode=remote
  • monero.prune=true
  • monero.prune=false
  • monero.rpc_lan_access=true
  • monero.rpc_lan_access=false
  • p2pool.pool=main
  • p2pool.pool=mini
  • p2pool.pool=nano
  • xvb.enabled=true
  • xvb.enabled=false
  • dashboard.secure=true
  • dashboard.secure=false
  • dashboard.tari_required=true
  • dashboard.tari_required=false
  • monero.clearnet_initial_sync=true
  • tari.clearnet_initial_sync=true

Per-scenario assertions (tests/integration/run.sh)

  • .env is owner-only (mode $envmode)
  • Caddyfile uses correct scheme
  • DASHBOARD_SECURE matches config
  • MONERO_CLEARNET_SYNC matches config (#183)
  • MONERO_RPC_BIND matches rpc_lan_access
  • Monero is synced (chain reusable by the matrix)
  • TARI_CLEARNET_SYNC matches config (#183)
  • TARI_REQUIRED env matches config
  • XVB_ENABLED matches config
  • backup archive contains .env
  • backup archive contains config.json
  • backup/rollback prerequisites present (writable backups/, tar)
  • both prune modes exercisable (live=$baseline_mode + supplied $opp_label chain at $opp_dir)
  • check
  • compose guard refuses the unauthenticated proxy API (#153)
  • container up: $svc
  • dashboard /api/state reachable
  • dashboard bound to localhost only (Caddy fronts it)
  • default-off stratum: no --access-password live (#152)
  • disk headroom on the live chain FS (${avail} GiB free)
  • memory ceiling live on $svc (#132)
  • monero auto-transitioned clearnet→Tor (#234)
  • monero display mode determinate ($dmode)
  • monero display mode present ($dmode)
  • monero sync panel reads done (dashboard)
  • monerod DNS checkpoints disabled (#161)
  • monerod absent in remote mode
  • monerod has no clearnet priority-node hostnames (#161)
  • monerod reported missing
  • monerod reports synced (RPC)
  • monerod running-but-unhealthy
  • monerod runs Tor-only in steady state — proxy present (#183/#234)
  • no clearnet egress — every app dials via Tor (#274/#270)
  • original PROXY_AUTH_TOKEN restored verbatim
  • pithead up fails closed (non-zero exit) on an empty PROXY_AUTH_TOKEN
  • pool actually changed
  • pool type
  • prune axis: live FS is snapshot-capable ($fstype) — the $opp_label variant can be built cheaply
  • re-apply is a no-op
  • restore preserves secrets
  • restore reverts the pool to the backed-up value
  • secrets intact (token + onions)
  • secrets intact after restore
  • secrets preserved across pool change
  • snapshot-isolated $baseline_mode chain on a CoW FS ($same_dir, $sfs) — destructive scenarios needn't touch the live chain
  • stack healthy again after token restore
  • stack is healthy (pithead status)
  • status OK after monerod recovery
  • status OK after node recovery
  • status OK after restart
  • status exit code is 0 (healthy)
  • status non-zero when monerod is down
  • status non-zero when monerod missing
  • status non-zero when monerod unhealthy
  • status non-zero when node down
  • stratum total hashes > 0
  • tari DNS sinkholed — no clearnet resolver (#162)
  • tari auto-transitioned clearnet→Tor (#234)
  • tari canonical config is always Tor (#234)
  • tari synced (required)
  • workers online (>= $EXPECTED_WORKERS)
  • xmrig-proxy dev-fee donate-level is explicit + live (#173)
  • xmrig-proxy stopped for failover

Harness self-test (tests/integration/selftest.sh) — 17 sections

  • overrides_to_jq: value typing
  • resolve_overrides: prerequisite gate (never mutates the canonical chain)
  • render_scenario_config: applies overrides, stays valid JSON
  • clearnet initial sync overrides + matrix (#183)
  • expected/absent services: profile gating
  • redact: secrets never leak into artifacts
  • matrix: every axis value is covered
  • scenarios: lookup helpers
  • rx: local exec runs in the stack dir
  • api_state + jq_get: parse a fixture
  • _pred_tari_synced: gates on .sync.tari.state
  • _pred_monero_panel_done: gates on .sync.monero.state
  • _pred_pool_ready: gates on .pool.type matching expected
  • _pred_hashes_flowing: gates on stratum.total_hashes > 0
  • dispatch loop: a stdin-draining child must not skip iterations
  • service_state parsing (fault-injection predicates)
  • assertion helpers: counters behave

Grand total: 632 enumerated cases/sections across the four tiers (plus the live lifecycle and fault-injection phases, which are exercised on a real server).