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.


eMutex cs_addrName;
    std::string addrName GUARDED_BY(cs_addrName);
    // 
    CService addrLocal GUARDED_BY(cs_addrLocal);
    mutable RecursiveMutex cs_addrLocal;
    //
    const bool m_inbound_onion{false};
public:
    NodeId GetId() const {
        return id;
    }
    uint64_t GetLocalNonce() const {
        return nLocalHostNonce;
    }
    int GetMyStartingHeight() const {
        return nMyStartingHeight;
    }
    int GetRefCount() const
    {
        assert(nRefCount >= 0);
        return nRefCount;
    }
    /**
     * Receive bytes from the buffer and deserialize them into messages.
     *
     * @param[in]   msg_bytes   The raw data
     * @param[out]  complete    Set True if at least one message has been
     *                          deserialized and is ready to be processed
     * @return  True if the peer should stay connected,
     *          False if the peer should be disconnected from.
     */
    bool ReceiveMsgBytes(Span<const uint8_t> msg_bytes, bool& complete);
    void SetCommonVersion(int greatest_common_version)
    {
        Assume(m_greatest_common_version == INIT_PROTO_VERSION);
        m_greatest_common_version = greatest_common_version;
    }
    int GetCommonVersion() const
    {
        return m_greatest_common_version;
    }
    CService GetAddrLocal() const;
    //
    void SetAddrLocal(const CService& addrLocalIn);
    CNode* AddRef()
    {
        nRefCount++;
        return this;
    }
    void Release()
    {
        nRefCount--;
    }
    void AddAddressKnown(const CAddress& _addr)
    {
        assert(m_addr_known);
        m_addr_known->insert(_addr.GetKey());
    }
    void PushAddress(const CAddress& _addr, FastRandomContext &insecure_rand)
    {
        // 
        // 
        // 
        const bool addr_format_supported = m_wants_addrv2 || _addr.IsAddrV1Compatible();
        // 
        // 
        // 
        assert(m_addr_known);
        if (_addr.IsValid() && m_addr_known->contains(_addr.GetKey()) && addr_forma