The eviction logic is one of the most important parts in our code base: a bug in the eviction logic could allow for attacker triggered network partitioning.

Unfortunately the eviction logic is currently not tested properly.

The unit tests and fuzz tests don't cover the eviction logic at all.

The functional tests cover some parts of the eviction logic but the coverage is spotty/incomplete.

Unfortunately `CConnman::AttemptToEvictConnection` is currently somewhat tricky to test.

To solve this I suggest simplifying `CConnman::AttemptToEvictConnection()` by introducing a new function ...

```
[[nodiscard]] Optional<NodeEvictionCandidate> SelectNodeToEvict(std::vector<NodeEvictionCandidate> vEvictionCandidates)
```

... which would be called from the now much simplified `CConnman::AttemptToEvictConnection`.

`SelectNodeToEvict` would contain all eviction selection logic and could thus be tested trivially.


::vector<unsigned char>& header) override;
};
/** Information about a peer */
class CNode
{
    friend class CConnman;
    friend struct ConnmanTestMsg;
public:
    std::unique_ptr<TransportDeserializer> m_deserializer;
    std::unique_ptr<TransportSerializer> m_serializer;
    // 
    std::atomic<ServiceFlags> nServices{NODE_NONE};
    SOCKET hSocket GUARDED_BY(cs_hSocket);
    size_t nSendSize{0}; // 
    size_t nSendOffset{0}; // 
    uint64_t nSendBytes GUARDED_BY(cs_vSend){0};
    std::deque<std::vector<unsigned char>> vSendMsg GUARDED_BY(cs_vSend);
    RecursiveMutex cs_vSend;
    RecursiveMutex cs_hSocket;
    RecursiveMutex cs_vRecv;
    RecursiveMutex cs_vProcessMsg;
    std::list<CNetMessage> vProcessMsg GUARDED_BY(cs_vProcessMsg);
    size_t nProcessQueueSize{0};
    RecursiveMutex cs_sendProcessing;
    uint64_t nRecvBytes GUARDED_BY(cs_vRecv){0};
    std::atomic<int64_t> nLastSend{0};
    std::atomic<int64_t> nLastRecv{0};
    const int64_t nTimeConnected;
    std::atomic<int64_t> nTimeOffset{0};
    // 
    const CAddress addr;
    // 
    const CAddress addrBind;
    std::atomic<int> nVersion{0};
    RecursiveMutex cs_SubVer;
    /**
     * cleanSubVer is a sanitized string of the user agent byte array we read
     * from the wire. This cleaned string can safely be logged or displayed.
     */
    std::string cleanSubVer GUARDED_BY(cs_SubVer){};
    bool m_prefer_evict{false}; // 
    bool HasPermission(NetPermissionFlags permission) const {
        return NetPermissions::HasFlag(m_permissionFlags, permission);
    }
    // 
    bool m_legacyWhitelisted{false};
    bool fClient{false}; // 
    bool m_limited_node{false}; //
    /**
     * Whether the peer has signaled support for receiving ADDRv2 (BIP155)
     * messages, implying a preference to receive ADDRv2 instead of ADDR ones.
     */
    std::atomic_bool m_wants_addrv2{false};
    std::atomic_bool fSuccessfullyConnected{false};
    // 
    // 
    std::atomic_bool fDisconnect{false};
    bool f