2011-04-25 12 views

Respuesta

11

Significa Tendrás que adaptar tu código de producción. Usando su ejemplo:

CSumWind definición de clase:

class CSumWnd : public CBaseWnd 
{ 

private: 
bool MethodA() 
}; 

burló definición CSumWnd clase:

class MockCSumWnd : public CBaseWnd 
{ 

private: 
MOCK_METHOD(MethodA, bool()); 
}; 

clase de producción que tienen que ser probado con la clase imitó CSumWind. Ahora se convierte en una plantilla para proporcionar el uso de la clase CSumWind en el código de producción y la clase MockCSumWnd en las pruebas.

template <class CSumWndClass> 
class TestedClass { 
//... 
    void useSumWnd(const CSumWndClass &a); 

private: 
    CSumWndClass sumWnd; 
}; 

instanciación de TestedClass en la producción:

TestedClass <CSumWnd> obj; 

instanciación del objeto en TestedClass ejecutable prueba:

TestedClass <MockCSumWnd> testObj; 
+0

para mantener su código de 'producción' limpia, me parece útil haz esto: plantilla clase TestedClassTemplate {...}, y luego haz typedef TestedClassTemplate TestedClass; – smehmood

+1

Consulte http://stackoverflow.com/q/1127918/49972 para obtener información sobre las consecuencias de hacer lo que propone. –

+0

Estoy frente a un problema en 'MOCK_METHOD (MethodA, bool());' https://stackoverflow.com/questions/46542373/how-to-mock-non-virtual-methods-using-googlemock?noredirect=1#comment80038793_46542373 Me aparece un error especificado en la pregunta anterior – CMouse

1

Trate CppFreeMock y algunos otros mencionados here.

Ejemplo:

string func() { 
    return "Non mocked."; 
} 

TEST(HelloWorld, First) { 
    EXPECT_CALL(*MOCKER(func), MOCK_FUNCTION()).Times(Exactly(1)) 
     .WillOnce(Return("Hello world.")); 
    EXPECT_EQ("Hello world.", func()); 
} 
+1

El segundo enlace para mí apunta a un inicio de sesión en OneDrive. Además, en lugar de utilizar solo "aquí" como descripción, sería mejor poner algo más descriptivo para que el documento aún pueda encontrarse si el enlace muere en el futuro. – PeterJ

+0

No tengo suficiente reputación para agregar más de 2 enlaces en una respuesta, actualice el enlace de "aquí", ya no es necesario iniciar sesión. El documento completo se puede encontrar en github. – Louix

0

Si no desea cambiar el código existente, que aquí hay una solución específica para VC++ que estoy trabajando (https://github.com/mazong1123/injectorpp). Los pasos breves son:

  1. Aproveche DbgHelp.h para recuperar los símbolos de todos los métodos y las direcciones de memoria de una clase. Básicamente recupera metainformación del archivo .pdb en tiempo de ejecución.
  2. Compare la entrada del usuario al símbolo del método de simulación con la salida del paso 1, obtenga la dirección de memoria del método de simulacros.
  3. Apalanque ventanas api WriteProcessMemory para cambiar los bytes de entrada del método to-mock, que es algo similar a: __asm ​​{move eax, 1; retirado}.

Pongamos aquí el código de tecla.

  1. Recupere los símbolos de los métodos y las direcciones de una clase. A continuación está la idea clave de la implementación. El código fuente completo es availiable en https://github.com/mazong1123/injectorpp/blob/master/injectorpp/ClassResolver.cpp

    // Retrieve class symbol. 
    if (SymGetTypeFromName(this->m_hProcess, modBase, className.c_str(), classSymbol) == FALSE) 
    { 
        throw; 
    } 
    
    // Get children of class - which are methods. 
    DWORD numChildren = 0; 
    if (SymGetTypeInfo(this->m_hProcess, classSymbol->ModBase, classSymbol->TypeIndex, TI_GET_CHILDRENCOUNT, &numChildren) == FALSE) 
    { 
        throw; 
    } 
    
    // Get methods info. 
    if (SymGetTypeInfo(this->m_hProcess, classSymbol->ModBase, classSymbol->TypeIndex, TI_FINDCHILDREN, methods) == FALSE) 
    { 
        throw; 
    } 
    
    // Retrieve all methods. 
    for (DWORD i = 0; i < numChildren; ++i) 
    { 
        ULONG curChild = methods->ChildId[i]; 
    
        // Resolve function. 
        Function resolvedFunction; 
        this->m_functionResolver->Resolve(classSymbol->ModBase, curChild, resolvedFunction); 
    
        // Add the resolved function to the output. 
        resolvedMethods.push_back(resolvedFunction); 
    } 
    
  2. Paso 2 es trivial. Solo se trata de comparar texto y procesar.

  3. Cómo inyectar la asm magia para cambiar el comportamiento método: (El código fuente completo está disponible en https://github.com/mazong1123/injectorpp/blob/master/injectorpp/BehaviorChanger.cpp)

    // A magic function to change the function behavior at runtime 
    // 
    // funcAddress - The address of the function to be changed from. 
    // expectedReturnValue - The return value should be changed to. 
    void BehaviorChanger::ChangeFunctionReturnValue(ULONG64 funcAddress, int expectedReturnValue) 
    { 
    
    
    // The purpose of this method is to change the return value 
    // to what ever int value we expected. 
    
    // Therefore, we just need to inject below asm to the header of specific function: 
    // 
    // mov eax, expectedValue 
    // ret 
    // 
    // Above asm code tells the function to return expectedValue immediately. 
    
    // Now let's prepare the asm command. 
    byte asmCommand[6]; 
    
    // mov 
    asmCommand[0] = 0xB8; 
    
    // The value. 
    asmCommand[1] = expectedReturnValue & 0xFF; 
    asmCommand[2] = (expectedReturnValue >> 8) & 0xFF; 
    asmCommand[3] = (expectedReturnValue >> 16) & 0xFF; 
    asmCommand[4] = (expectedReturnValue >> 24) & 0xFF; 
    
    // ret 
    asmCommand[5] = 0xC3; 
    
    WriteProcessMemory((HANDLE)-1, (void*)funcAddress, asmCommand, 6, 0); 
    } 
    
+0

Parece interesante. Me encantaría ver algo similar para GCC/Clang. – hedayat

+0

@hedayat Estoy planeando hacer esto. Recientemente, casi he terminado la parte x86 de Windows. Estancia sintonizada. –

Cuestiones relacionadas