test: Add mockable steady clock, tests for PCP and NATPMP implementations #31022

pull laanwj wants to merge 4 commits into bitcoin:master from laanwj:2024-10-pcp-tests changing 9 files +638 −15
  1. laanwj commented at 8:52 pm on October 2, 2024: member

    Add a NodeSteadyClock, a steady_clock that can be mocked with millisecond precision. Use this in the PCP implementation.

    Then add a mock for a simple scriptable UDP server,, which is used to test various code paths (including successful mappings, timeouts and errors) in the PCP and NATPMP implementations.

    Includes “net: Add optional length checking to CService::SetSockAddr” from #31014 as a prerequisite.

  2. laanwj added the label Tests on Oct 2, 2024
  3. laanwj added the label Utils/log/libs on Oct 2, 2024
  4. DrahtBot commented at 8:52 pm on October 2, 2024: contributor

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Code Coverage & Benchmarks

    For details see: https://corecheck.dev/bitcoin/bitcoin/pulls/31022.

    Reviews

    See the guideline for information on the review process.

    Type Reviewers
    Concept ACK dergoegge, darosior

    If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #31549 (fuzz: Abort if system time is called without mock time being set by marcofleon)
    • #31014 (net: Use GetAdaptersAddresses to get local addresses on Windows by laanwj)
    • #30988 (Split CConnman by vasild)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  5. DrahtBot renamed this:
    test: Add mockable steady clock, tests for PCP and NATPMP implementations
    test: Add mockable steady clock, tests for PCP and NATPMP implementations
    on Oct 2, 2024
  6. DrahtBot added the label Needs rebase on Oct 2, 2024
  7. laanwj force-pushed on Oct 3, 2024
  8. net: Add optional length checking to CService::SetSockAddr
    In almost all cases (the only exception is `getifaddrs`), we know the
    size of the data passed into SetSockAddr, so we can check this to be
    what is expected.
    39f7c14621
  9. laanwj force-pushed on Oct 3, 2024
  10. laanwj force-pushed on Oct 3, 2024
  11. DrahtBot added the label CI failed on Oct 3, 2024
  12. laanwj force-pushed on Oct 3, 2024
  13. bitcoin deleted a comment on Oct 3, 2024
  14. laanwj removed the label Needs rebase on Oct 3, 2024
  15. DrahtBot removed the label CI failed on Oct 3, 2024
  16. bitcoin deleted a comment on Oct 3, 2024
  17. in src/util/time.h:26 in 85a41cb90e outdated
    21@@ -22,6 +22,15 @@ struct NodeClock : public std::chrono::system_clock {
    22 };
    23 using NodeSeconds = std::chrono::time_point<NodeClock, std::chrono::seconds>;
    24 
    25+/** Mockable steady clock in the context of tests, otherwise the system steady clock */
    26+struct NodeSteadyClock : public std::chrono::steady_clock {
    


    dergoegge commented at 9:40 am on October 3, 2024:
    Could we turn SteadyClock into this struct instead? Having both types could be confusing.

    laanwj commented at 10:01 am on October 3, 2024:

    sure, fine with me, agree it’s less confusing (NodeSteadyClock says nothing at all) though i wasn’t sure which of the current usages should be mockable and didn’t want to decide that here

    edit: i’ll rename the structure to something clearer like MockableSteadyClock how about that?


    dergoegge commented at 3:22 pm on October 3, 2024:

    i wasn’t sure which of the current usages should be mockable and didn’t want to decide that here

    fair enough!

    MockableSteadyClock sgtm!


    laanwj commented at 11:29 am on October 4, 2024:

    Should be unambigious now, i’ve renamed it and the methods to set/clear the mock time are included on the clock itself.

     0/**
     1 * Version of SteadyClock that is mockable in the context of tests (set the
     2 * current value with SetMockTime), otherwise the system steady clock.
     3 */
     4struct MockableSteadyClock : public std::chrono::steady_clock {
     5    using time_point = std::chrono::time_point<MockableSteadyClock>;
     6    /** Return current system time or mocked time, if set */
     7    static time_point now() noexcept;
     8    static std::time_t to_time_t(const time_point&) = delete; // unused
     9    static time_point from_time_t(std::time_t) = delete;      // unused
    10
    11    /** Set mock time for testing. */
    12    static void SetMockTime(std::chrono::milliseconds mock_time_in);
    13
    14    /** Clear mock time, go back to system steady clock. */
    15    static void ClearMockTime();
    16};
    
  18. in src/util/time.cpp:58 in 85a41cb90e outdated
    53+};
    54+
    55+void SetMockSteadyTime(std::chrono::milliseconds mock_time_in)
    56+{
    57+    Assert(mock_time_in >= 0s);
    58+    g_mock_steady_time.store(mock_time_in, std::memory_order_relaxed);
    


    dergoegge commented at 9:48 am on October 3, 2024:

    My approach for this would have been to reuse SetMockTime, which would set g_mock_time to the requested mocktime and g_mock_steady_time to max(mock_time_in, g_mock_steady_time) (to ensure it only ever increases).

    The benefit of that approach would be that all existing tests that make use of mock time would now also mock steady time (assuming NodeSteadyClock is used throughout).

    I never implemented and tested this but I was curious if you considered this as well?


    laanwj commented at 10:04 am on October 3, 2024:

    i don’t know.

    i like being able to mock them seperately, and millisecond resolultion instead of second resolution is kind of nice here because it tends to be used for deadlines and timeouts, seconds are kind of clunky there.

    also conceptually i think “max(mock_time_in, g_mock_steady_time)” is a wrong representation of how monotonic time works, it’s basically a CPU cycle counter (from system startup, usually), it isn’t linked to wall time or updates of that at all.

    The reference point generally doesn’t matter, only differences do; in my current tests i in fact reset it in every test case.


    dergoegge commented at 3:25 pm on October 3, 2024:

    in my current tests i in fact reset it in every test case.

    Right, this wouldn’t work with my approach as this is a global.

  19. dergoegge commented at 9:55 am on October 3, 2024: member

    Concept ACK

    Left some comments on the approach for the steady mock time.

  20. laanwj force-pushed on Oct 4, 2024
  21. util: Add mockable steady_clock
    This adds a NodeSteadyClock, which is a steady_clock that can be mocked
    with millisecond precision.
    159e2ec274
  22. net: Use mockable steady clock in PCP implementation
    This will be needed for the test harness.
    21d6f45ebb
  23. test: Add tests for PCP and NATPMP implementations
    Add a mock for a simple scriptable UDP server, and use this to test
    various code paths (including successful mappings, timeouts and errors)
    in the PCP and NATPMP implementations.
    258b2856cd
  24. laanwj force-pushed on Oct 21, 2024
  25. darosior commented at 2:49 pm on November 8, 2024: member
    Concept ACK

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-12-22 00:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me