summaryrefslogtreecommitdiffstats
path: root/src/dmclock/test/test_test_client.cc
blob: 11cbd74b15777ab4631b86bf3d2f4fe5b359acc9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab

/*
 * Copyright (C) 2016 Red Hat Inc.
 *
 * Author: J. Eric Ivancich <ivancich@redhat.com>
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version
 * 2.1, as published by the Free Software Foundation.  See file
 * COPYING.
 */


#include <atomic>
#include <thread>
#include <chrono>
#include <iostream>

#include "gtest/gtest.h"

#include "sim_recs.h"
#include "sim_client.h"

#include "test_dmclock.h"


using namespace std::placeholders;

namespace dmc = crimson::dmclock;
namespace test = crimson::test_dmc;
namespace sim = crimson::qos_simulation;

using TimePoint = std::chrono::time_point<std::chrono::system_clock>;

static TimePoint now() { return std::chrono::system_clock::now(); }


TEST(test_client, full_bore_timing) {
  std::atomic_ulong count(0);

  ServerId server_id = 3;

  sim::TestResponse resp(0);
  dmc::PhaseType resp_params = dmc::PhaseType::priority;
  test::DmcClient* client;
  const sim::Cost request_cost = 1u;

  auto start = now();
  client =
    new test::DmcClient(ClientId(0),
			[&] (const ServerId& server,
			     const sim::TestRequest& req,
			     const ClientId& client_id,
			     const dmc::ReqParams& req_params) {
			  ++count;
			  client->receive_response(resp, client_id, resp_params, request_cost);
			},
			[&] (const uint64_t seed) -> ServerId& {
			  return server_id;
			},
			test::dmc_client_accumulate_f,
			1000, // ops to run
			100, // iops goal
			5); // outstanding ops allowed
  client->wait_until_done();
  auto end = now();
  EXPECT_EQ(1000u, count) << "didn't get right number of ops";

  int milliseconds = (end - start) / std::chrono::milliseconds(1);
  EXPECT_LT(10000, milliseconds) << "timing too fast to be correct";
  EXPECT_GT(12000, milliseconds) << "timing suspiciously slow";

  delete client;
}


TEST(test_client, paused_timing) {
  std::atomic_ulong count(0);
  std::atomic_ulong unresponded_count(0);
  std::atomic_bool auto_respond(false);

  ClientId my_client_id = 0;
  ServerId server_id = 3;

  sim::TestResponse resp(0);
  dmc::PhaseType resp_params = dmc::PhaseType::priority;
  const uint64_t request_cost = 1u;
  test::DmcClient* client;

  auto start = now();
  client =
    new test::DmcClient(my_client_id,
			[&] (const ServerId& server,
			     const sim::TestRequest& req,
			     const ClientId& client_id,
			     const dmc::ReqParams& req_params) {
			  ++count;
			  if (auto_respond.load()) {
			    client->receive_response(resp, client_id, resp_params, request_cost);
			  } else {
			    ++unresponded_count;
			  }
			},
			[&] (const uint64_t seed) -> ServerId& {
			  return server_id;
			},
			test::dmc_client_accumulate_f,

			1000, // ops to run
			100, // iops goal
			50); // outstanding ops allowed
  std::thread t([&]() {
      std::this_thread::sleep_for(std::chrono::seconds(5));
      EXPECT_EQ(50u, unresponded_count.load()) <<
	"should have 50 unresponded calls";
      auto_respond = true;
      // respond to those 50 calls
      for(int i = 0; i < 50; ++i) {
	client->receive_response(resp, my_client_id, resp_params, 1);
	--unresponded_count;
      }
    });

  client->wait_until_done();
  auto end = now();
  int milliseconds = (end - start) / std::chrono::milliseconds(1);

  // the 50 outstanding ops allowed means the first half-second of
  // requests get responded to during the 5 second pause. So we have
  // to adjust our expectations by a half-second.
  EXPECT_LT(15000 - 500, milliseconds) << "timing too fast to be correct";
  EXPECT_GT(17000 - 500, milliseconds) << "timing suspiciously slow";
  t.join();

  delete client;
}