internal-tests-linux.cpp
Go to the documentation of this file.
1 #include "catch/catch.hpp"
2 #include <thread>
3 #include <string>
4 #include <linux/backend-v4l2.h>
5 #include <sys/types.h>
6 #include <sys/wait.h>
7 #include <semaphore.h>
8 
9 using namespace librealsense::platform;
10 
11 TEST_CASE("named_mutex_threads", "[code]")
12 {
13  class locker_test
14  {
15  std::mutex _m0, _m1;
16  bool _go_0, _go_1;
17  std::condition_variable _cv0, _cv1;
18  bool _actual_test;
19 
20  std::string _device_path;
21  public:
22  locker_test(const std::string& device_path, bool actual_test):
23  _go_0(false),
24  _go_1(false),
25  _actual_test(actual_test),
26  _device_path(device_path)
27  {
28  };
29 
30  void func_0()
31  {
32  {
33  std::unique_lock<std::mutex> lk(_m0);
34  _cv0.wait(lk, [this]{return _go_0;});
35  }
36  named_mutex mutex0(_device_path, 0);
37  if (_actual_test)
38  {
39  mutex0.lock();
40  }
41  {
42  std::unique_lock<std::mutex> lk(_m0);
43  _go_0 = false;
44  }
45  }
46  void func_1()
47  {
48  {
49  std::unique_lock<std::mutex> lk(_m1);
50  _cv1.wait(lk, [this]{return _go_1;});
51  }
52  named_mutex mutex1(_device_path, 0);
53  mutex1.lock();
54  {
55  std::lock_guard<std::mutex> lk_gm(_m1);
56  _go_1 = false;
57  }
58  _cv1.notify_all();
59  {
60  std::unique_lock<std::mutex> lk(_m1);
61  _cv1.wait(lk, [this]{return _go_1;});
62  }
63  }
64 
65  void run_test()
66  {
67  bool test_ok(false);
68 
69  std::thread t0 = std::thread([this](){func_0();});
70  std::thread t1 = std::thread([this](){func_1();});
71  // Tell Thread 1 to lock named_mutex.
72  {
73  std::lock_guard<std::mutex> lk_gm(_m1);
74  _go_1 = true;
75  }
76  _cv1.notify_all();
77  // Wait for Thread 1 to acknowledge lock.
78  {
79  std::unique_lock<std::mutex> lk(_m1);
80  _cv1.wait(lk, [this]{return !_go_1;});
81  }
82  // Tell Thread 0 to lock named_mutex.
83  {
84  std::lock_guard<std::mutex> lk_gm(_m0);
85  _go_0 = true;
86  }
87  _cv0.notify_all();
88  // Give Thread 2 seconds opportunity to lock.
89  std::this_thread::sleep_for(std::chrono::milliseconds(2000));
90  {
91  std::lock_guard<std::mutex> lk_gm(_m0);
92  // test_ok if thread 0 didn't manage to change value of _go_0.
93  test_ok = (_go_0 == _actual_test);
94  }
95  // Tell thread 1 to finish and release named_mutex.
96  {
97  std::lock_guard<std::mutex> lk_gm(_m1);
98  _go_1 = true;
99  }
100  _cv1.notify_all();
101  t1.join();
102  t0.join();
103  REQUIRE(test_ok);
104  }
105  };
106  std::string device_path("./named_mutex_test");
107  int fid(-1);
108  if( access( device_path.c_str(), F_OK ) == -1 )
109  {
110  fid = open(device_path.c_str(), O_CREAT | O_RDWR, 0666);
111  close(fid);
112  }
113  bool actual_test;
114  SECTION("self-validation")
115  {
116  actual_test = false;
117  }
118  SECTION("actual-test")
119  {
120  actual_test = true;
121  }
122 
123  locker_test _test(device_path, actual_test);
124  _test.run_test();
125 }
126 
127 TEST_CASE("named_mutex_processes", "[code]")
128 {
129  std::string device_path("./named_mutex_test");
130  int fid(-1);
131  if( access( device_path.c_str(), F_OK ) == -1 )
132  {
133  fid = open(device_path.c_str(), O_CREAT | O_RDWR, 0666);
134  close(fid);
135  }
136 
137  sem_unlink("test_semaphore1");
138  sem_t *sem1 = sem_open("test_semaphore1", O_CREAT|O_EXCL, S_IRWXU, 0);
139  CHECK_FALSE(sem1 == SEM_FAILED);
140  sem_unlink("test_semaphore2");
141  sem_t *sem2 = sem_open("test_semaphore2", O_CREAT|O_EXCL, S_IRWXU, 0);
142  CHECK_FALSE(sem2 == SEM_FAILED);
143  pid_t pid_0 = getpid();
144  pid_t pid = fork();
145  bool actual_test;
146  SECTION("self-validation")
147  {
148  actual_test = false;
149  }
150  SECTION("actual-test")
151  {
152  actual_test = true;
153  }
154  if (pid == 0) // child
155  {
156  signal(SIGTERM, [](int signum) { exit(1); });
157 
158  sem_wait(sem1);
159  sem_post(sem2);
160  named_mutex mutex1(device_path, 0);
161  if (actual_test)
162  mutex1.lock();
163  exit(0);
164  }
165  else
166  {
167  named_mutex mutex1(device_path, 0);
168  mutex1.lock();
169  CHECK_FALSE(sem_post(sem1) < 0);
170  sem_wait(sem2);
171  std::this_thread::sleep_for(std::chrono::milliseconds(2000));
172  int status;
173  pid_t w = waitpid(pid, &status, WNOHANG);
174  CHECK_FALSE(w == -1);
175  bool child_alive(w == 0);
176  if (child_alive) {
177  int res = kill(pid,SIGTERM);
178  pid_t w = waitpid(pid, &status, 0);
179  }
180  if (fid > 0)
181  {
182  remove(device_path.c_str());
183  }
184  sem_unlink("test_semaphore1");
185  sem_close(sem1);
186  sem_unlink("test_semaphore2");
187  sem_close(sem2);
188  REQUIRE(child_alive == actual_test);
189  }
190 }
191 
def run_test(self, configuration=None, log_path=None)
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t0
Definition: glext.h:9721
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
Definition: glext.h:9721
GLdouble GLdouble GLdouble w
GLsizei const GLchar *const * string
status
Defines return codes that SDK interfaces use. Negative values indicate errors, a zero value indicates...
#define SECTION(...)
Definition: catch.hpp:17438
REQUIRE(n_callbacks==1)
static const textual_icon exit
Definition: model-views.h:254
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:2180
GLuint res
Definition: glext.h:8856
TEST_CASE("named_mutex_threads","[code]")
CHECK_FALSE(inverse(inverse(p))==p)


librealsense2
Author(s): Sergey Dorodnicov , Doron Hirshberg , Mark Horn , Reagan Lopez , Itay Carpis
autogenerated on Mon May 3 2021 02:47:17