aboutsummaryrefslogblamecommitdiffstats
path: root/library/cpp/testing/common/probe.h
blob: 19910979b56382d5576dad4536598dfe2133fe7c (plain) (tree)
1
2
3
4
5
6
7
8
9
            
                                
 
                    
                                                                                    
 
                                                                                                            
 







                                  
 
                                
 


                                  
 



                                                                                  
 



                                                      
 




                                                               
 



                                                            
 


                                                      
 





                                           
 






                                                 
 





                                            
 






                                            
 




                                              
         






                                            
         
 





                                                
 





                                            
         
 


                             
 
                                    
         
 



                            
                       
#pragma once

#include <util/system/yassert.h>

namespace NTesting {
    ////////////////////////////////////////////////////////////////////////////////

    // Below there is a serie of probe classes for testing construction/destruction copying/moving of class.
    // for examples see tests in probe_ut.cpp

    struct TProbeState {
        int Constructors = 0;
        int Destructors = 0;
        int ShadowDestructors = 0;
        int CopyConstructors = 0;
        int CopyAssignments = 0;
        int MoveConstructors = 0;
        int MoveAssignments = 0;
        int Touches = 0;

        TProbeState() = default;

        void Reset() {
            *this = TProbeState{};
        }
    };

    // Used for probing the number of copies that occur if a type must be coerced.
    class TCoercibleToProbe {
    public:
        TProbeState* State;
        TProbeState* ShadowState;

    public:
        explicit TCoercibleToProbe(TProbeState* state)
            : State(state)
            , ShadowState(state)
        {}

    private:
        TCoercibleToProbe(const TCoercibleToProbe&);
        TCoercibleToProbe(TCoercibleToProbe&&);
        TCoercibleToProbe& operator=(const TCoercibleToProbe&);
        TCoercibleToProbe& operator=(TCoercibleToProbe&&);
    };

    // Used for probing the number of copies in an argument.
    class TProbe {
    public:
        TProbeState* State;
        TProbeState* ShadowState;

    public:
        static TProbe ExplicitlyCreateInvalidProbe() {
            return TProbe();
        }

        explicit TProbe(TProbeState* state)
            : State(state)
            , ShadowState(state)
        {
            Y_ASSERT(State);
            ++State->Constructors;
        }

        ~TProbe() {
            if (State) {
                ++State->Destructors;
            }
            if (ShadowState) {
                ++ShadowState->ShadowDestructors;
            }
        }

        TProbe(const TProbe& other)
            : State(other.State)
            , ShadowState(other.ShadowState)
        {
            Y_ASSERT(State);
            ++State->CopyConstructors;
        }

        TProbe(TProbe&& other)
            : State(other.State)
            , ShadowState(other.ShadowState)
        {
            Y_ASSERT(State);
            other.State = nullptr;
            ++State->MoveConstructors;
        }

        TProbe(const TCoercibleToProbe& other)
            : State(other.State)
            , ShadowState(other.ShadowState)
        {
            Y_ASSERT(State);
            ++State->CopyConstructors;
        }

        TProbe(TCoercibleToProbe&& other)
            : State(other.State)
            , ShadowState(other.ShadowState)
        {
            Y_ASSERT(State);
            other.State = nullptr;
            ++State->MoveConstructors;
        }

        TProbe& operator=(const TProbe& other) {
            State = other.State;
            ShadowState = other.ShadowState;
            Y_ASSERT(State);
            ++State->CopyAssignments;
            return *this;
        }

        TProbe& operator=(TProbe&& other) {
            State = other.State;
            ShadowState = other.ShadowState;
            Y_ASSERT(State);
            other.State = nullptr;
            ++State->MoveAssignments;
            return *this;
        }

        void Touch() const {
            Y_ASSERT(State);
            ++State->Touches;
        }

        bool IsValid() const {
            return nullptr != State;
        }

    private:
        TProbe()
            : State(nullptr)
        {}
    };
} // namespace NTesting