libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
shared_mem.cpp
Go to the documentation of this file.
1 /******************************************************************************
2 ** Copyright © 2019 by J.M.McGuiness, coder@hussar.me.uk
3 **
4 ** This library is free software; you can redistribute it and/or
5 ** modify it under the terms of the GNU Lesser General Public
6 ** License as published by the Free Software Foundation; either
7 ** version 2.1 of the License, or (at your option) any later version.
8 **
9 ** This library is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 ** Lesser General Public License for more details.
13 **
14 ** You should have received a copy of the GNU Lesser General Public
15 ** License along with this library; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 
19 #include "stdafx.h"
20 
21 #define BOOST_TEST_MODULE libjmmcg_tests
22 #include <boost/test/included/unit_test.hpp>
23 
24 #include "config.h"
26 
27 #include "core/shared_mem.hpp"
28 
29 #include <cstdlib>
30 #include <future>
31 
32 static const std::string name("shared_mem_test");
33 static constexpr std::size_t size=sizeof(std::uint64_t)*10;
34 
35 using namespace libjmmcg;
36 
38  class ensure_exits {
39  public:
40  explicit ensure_exits(shared_data &data) noexcept(true)
41  : data_(data) {}
42  ~ensure_exits() noexcept(true) {
43  data_.exit_child=true;
44  }
45 
46  private:
47  shared_data &data_;
48  };
49 
52 
54  while (!data->subproc_started) {
55  std::this_thread::yield();
56  }
57  }
58 
59  void new_data() {
60  data->changed=!data->changed;
61  }
62 
64  const bool old=data->changed;
65  while (data->changed==old) {
66  std::this_thread::yield();
67  }
68  }
69 };
70 
71 BOOST_AUTO_TEST_SUITE(shared_mem_test)
72 
73 BOOST_AUTO_TEST_CASE(ctor) {
74  BOOST_CHECK_NO_THROW(shared_mem shm(name, size));
75 }
76 
77 BOOST_AUTO_TEST_CASE(create_shms_shared_another) {
78  shared_mem shm(name, size);
79  shared_mem shm_shared(name, size);
80 }
81 
82 BOOST_AUTO_TEST_CASE(verify_mapped_Addr_not_nullptr) {
83  shared_mem shm(name, size);
84  BOOST_CHECK_NE(shm.get<void>(), nullptr);
85 }
86 
87 BOOST_AUTO_TEST_CASE(write_word_to_memory_and_sync) {
88  shared_mem shm(name, size);
89  std::uint64_t *mem=shm.get<std::uint64_t>();
90  *mem=42;
91  BOOST_CHECK_EQUAL(*shm.get<std::uint64_t>(), 42);
92  BOOST_CHECK_NO_THROW(shm.sync(shm.get<std::uint64_t>(), sizeof(std::uint64_t)));
93  BOOST_CHECK_EQUAL(*shm.get<std::uint64_t>(), 42);
94  BOOST_CHECK_NO_THROW(shm.sync(shm.get<std::uint64_t>(), sizeof(std::uint64_t), shared_mem::req_update_wait));
95  BOOST_CHECK_EQUAL(*shm.get<std::uint64_t>(), 42);
96  *mem=68;
97  BOOST_CHECK_EQUAL(*shm.get<std::uint64_t>(), 68);
98  BOOST_CHECK_NO_THROW(shm.sync(shm.get<std::uint64_t>(), sizeof(std::uint64_t)));
99  BOOST_CHECK_EQUAL(*shm.get<std::uint64_t>(), 68);
100  BOOST_CHECK_NO_THROW(shm.sync(shm.get<std::uint64_t>(), sizeof(std::uint64_t), shared_mem::req_update_wait));
101  BOOST_CHECK_EQUAL(*shm.get<std::uint64_t>(), 68);
102 }
103 
104 BOOST_AUTO_TEST_CASE(create_shms_shared_another_writes) {
105  shared_mem shm(name, size);
106  shared_mem shm_shared(name, size);
107  std::uint64_t *mem=shm.get<std::uint64_t>();
108  *mem=42;
109  std::uint64_t *mem_shared=shm_shared.get<std::uint64_t>();
110  BOOST_CHECK_EQUAL(*mem_shared, *mem);
111  *mem_shared=68;
112  BOOST_CHECK_EQUAL(*mem_shared, *mem);
113 }
114 
115 BOOST_AUTO_TEST_CASE(create_shm_and_child_in_bg) {
116  create_shm_and_child shm_and_child;
117  int exit_code=-1;
118  {
119  const create_shm_and_child::ensure_exits exit(*shm_and_child.data);
120  exit_code=std::system(JMMCG_SHAREDMEM_SUBPROC_NAME " &");
121  BOOST_CHECK_NO_THROW(shm_and_child.wait_for_subproc_to_start());
122  shm_and_child.data->ping=true;
123  BOOST_CHECK_NO_THROW(shm_and_child.new_data());
124  BOOST_CHECK_NO_THROW(shm_and_child.wait_for_new_data());
125  BOOST_CHECK_EQUAL(shm_and_child.data->pong, true);
126  }
127  BOOST_CHECK_EQUAL(exit_code, 0);
128 }
129 
130 BOOST_AUTO_TEST_CASE(create_shm_and_child_controlled_by_thread) {
131  create_shm_and_child shm_and_child;
132  auto get_subproc_ret_code=std::async(
133  std::launch::async,
134  []() {
135  return std::system(JMMCG_SHAREDMEM_SUBPROC_NAME);
136  }
137  );
138  {
139  const create_shm_and_child::ensure_exits exit(*shm_and_child.data);
140  BOOST_CHECK_NO_THROW(shm_and_child.wait_for_subproc_to_start());
141  shm_and_child.data->ping=true;
142  BOOST_CHECK_NO_THROW(shm_and_child.new_data());
143  BOOST_CHECK_NO_THROW(shm_and_child.wait_for_new_data());
144  BOOST_CHECK_EQUAL(shm_and_child.data->pong, true);
145  }
146  // No bloody idea why we get this weird difference...
147 #ifdef NDEBUG
148  BOOST_CHECK_EQUAL(get_subproc_ret_code.get(), 0);
149 #else
150  BOOST_CHECK_EQUAL(get_subproc_ret_code.get(), 256);
151 #endif
152 }
153 
154 BOOST_AUTO_TEST_SUITE_END()