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.


     * Determine whether we're already connected to a given address, in order to
     * avoid initiating duplicate connections.
     */
    bool AlreadyConnectedToAddress(const CAddress& addr);
    bool AttemptToEvictConnection();
    CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, ConnectionType conn_type);
    void AddWhitelistPermissionFlags(NetPermissionFlags& flags, const CNetAddr &addr) const;
    void DeleteNode(CNode* pnode);
    NodeId GetNewNodeId();
    size_t SocketSendData(CNode *pnode) const;
    void DumpAddresses();
    // 
    void RecordBytesRecv(uint64_t bytes);
    void RecordBytesSent(uint64_t bytes);
    /**
     * Return vector of current BLOCK_RELAY peers.
     */
    std::vector<CAddress> GetCurrentBlockRelayOnlyConns() const;
    // 
    static bool NodeFullyConnected(const CNode* pnode);
    // 
    RecursiveMutex cs_totalBytesRecv;
    RecursiveMutex cs_totalBytesSent;
    uint64_t nTotalBytesRecv GUARDED_BY(cs_totalBytesRecv) {0};
    uint64_t nTotalBytesSent GUARDED_BY(cs_totalBytesSent) {0};
    // 
    uint64_t nMaxOutboundTotalBytesSentInCycle GUARDED_BY(cs_totalBytesSent) {0};
    std::chrono::seconds nMaxOutboundCycleStartTime GUARDED_BY(cs_totalBytesSent) {0};
    uint64_t nMaxOutboundLimit GUARDED_BY(cs_totalBytesSent);
    // 
    int64_t m_peer_connect_timeout;
    // 
    // 
    std::vector<NetWhitelistPermissions> vWhitelistedRange;
    unsigned int nSendBufferMaxSize{0};
    unsigned int nReceiveFloodSize{0};
    std::vector<ListenSocket> vhListenSocket;
    std::atomic<bool> fNetworkActive{true};
    bool fAddressesInitialized{false};
    CAddrMan addrman;
    std::deque<std::string> m_addr_fetches GUARDED_BY(m_addr_fetches_mutex);
    RecursiveMutex m_addr_fetches_mutex;
    std::vector<std::string> vAddedNodes GUARDED_BY(cs_vAddedNodes);
    RecursiveMutex cs_vAddedNodes;
    std::vector<CNode*> vNodes GUARDED_BY(cs_vNodes);
    std::list<CNode*> vNodesDisconnected;
    mutable Recursive