1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4//*****************************************************************************
5// File: DataTest.h
6//
7
8//
9// Implement a self-test for the correct detection of when the target holds a
10// lock we encounter in the DAC.
11//
12//*****************************************************************************
13
14#ifndef DATA_TEST_H
15#define DATA_TEST_H
16
17// This class is used to test our ability to detect from the RS when the target has taken a lock.
18// When the DAC executes a code path that takes a lock, we need to know if the target is holding it.
19// If it is, then we assume that the locked data is in an inconsistent state. In that case, we don't
20// want to report the data; we just want to throw an exception.
21// This functionality in this class lets us take a lock on the LS and then signal the RS to try to
22// detect whether the lock is held. The main function in this class is TestDataSafety. It deterministically
23// signals the RS at key points to execute a code path that takes a lock and also passes a flag to indicate
24// whether the LS actually holds the lock. With this information, we can ascertain that our lock detection
25// code is working correctly. Without this special test function, it would be nearly impossible to test this
26// in any kind of deterministic way.
27//
28// The test will run in either debug or retail builds, as long as the environment variable TestDataConsistency
29// is turned on. It runs once in code:Debugger::Startup. The RS part of the test is in the cases
30// DB_IPCE_TEST_CRST and DB_IPCE_TEST_RWLOCK in code:CordbProcess::RawDispatchEvent.
31class DataTest
32{
33public:
34 // constructor
35 DataTest():
36 m_crst1(CrstDataTest1),
37 m_crst2(CrstDataTest2),
38 m_rwLock(COOPERATIVE_OR_PREEMPTIVE, LOCK_TYPE_DEFAULT) {};
39
40 // Takes a series of locks in various ways and signals the RS to test the locks at interesting
41 // points to ensure we reliably detect when the LS holds a lock.
42 void TestDataSafety();
43private:
44 // Send an event to the RS to signal that it should test to determine if a crst is held.
45 // This is for testing purposes only.
46 void SendDbgCrstEvent(Crst * pCrst, bool okToTake);
47
48 // Send an event to the RS to signal that it should test to determine if a SimpleRWLock is held.
49 // This is for testing purposes only.
50 void SendDbgRWLockEvent(SimpleRWLock * pRWLock, bool okToTake);
51
52private:
53 // The locks must be data members (rather than locals in TestDataSafety) so we can ensure that
54 // they are target instances.
55 Crst m_crst1, m_crst2; // crsts to be taken for testing
56 SimpleRWLock m_rwLock; // SimpleRWLock to be taken for testing
57};
58#endif // DATA_TEST_H
59