How to solve access violation reading location in google test?

310 Views Asked by At

I am trying to run Google test with the below code. I am reading some memory location for register value with code similar to the examples below.

Header file :

typedef union MYREG
{
  uint32_t u32reg;
  uint8_t  au8byte[4];
} MYREG_t;

#define SET_VALUE       (0x00000002)
#define TEST_REGISTER   ((volatile MYREG_t*)0x2025111BUL)

In code I am reading and writing values as

void testcode()
{
  TEST_REGISTER->u32reg |= SET_VALUE;
  call_another_funct();
}

When i try to run google test by writing a test case for this function

TEST_F(sample_test, check)
{
  testcode();
}

I am getting below SEH error

First-chance exception at 0x0036B28F in test.exe: 0xC0000005: Access violation reading location 0x2025111B.
Unknown file: error: SEH exception with code 0xC0000005 thrown in the test body.

What is going wrong here ? Any suggestion would helpful for me to understand the error.

1

There are 1 best solutions below

0
Pepijn Kramer On

Example of dependency injection for unit testability :

#include <memory>
#include <utility>

//-----------------------------------------------------------------------------
// define an interface (abstract base class) to communicate with your register
class register_itf
{
public:
    virtual ~register_itf() = default;

    virtual void write(const std::uint32_t value) = 0;
    virtual std::uint32_t read() const noexcept = 0;

protected:
    register_itf() = default;
};

//-----------------------------------------------------------------------------
// toy example of real register

class hardware_register final :
    public register_itf
{
public:
    explicit hardware_register(std::uint32_t* address) :
        m_address(address)
    {
    }
    ~hardware_register() override = default;

    void write(const std::uint32_t value) override
    {
        *m_address = value;
    }

    std::uint32_t read() const noexcept override
    {
        return *m_address;
    }

private:
    volatile std::uint32_t* m_address;
};

//-----------------------------------------------------------------------------
// you can also make this a google mock to test if it has been called etc...

class simulated_register final :
    public register_itf
{
public:
    simulated_register() = default;
    ~simulated_register() override = default;

    void write(const std::uint32_t value) override
    {
        m_value = value;
    }

    std::uint32_t read() const noexcept override
    {
        return m_value;
    }
    
private:
    std::uint32_t m_value;
};

//-----------------------------------------------------------------------------
// a device with a register, use dependency injection
// to inject a real or a simulated register

class device_t
{
public:
    explicit device_t(std::unique_ptr<register_itf>&& reg) :
        m_register(std::move(reg))
    {
    }

    void reset()
    {
        m_register->write(0x01);
    }

private:
    std::unique_ptr<register_itf> m_register;
};


int main()
{
    // production code on real hardware
    //device_t device{ std::make_unique<hardware_register>(0x2025111BUL) };
    
    // unit test code
    device_t device{ std::make_unique<simulated_register>() };

    // functional code using the register will be the same on production/test
    device.reset();

    return 1;

}