test/hotspot/gtest/jfr/test_networkUtilization.cpp
changeset 50879 d90c3cbf13df
child 50894 e8d55141afd2
equal deleted inserted replaced
50878:fb7800b66c92 50879:d90c3cbf13df
       
     1 /*
       
     2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  *
       
    23  */
       
    24 
       
    25 #include "precompiled.hpp"
       
    26 
       
    27 // This test performs mocking of certain JVM functionality. This works by
       
    28 // including the source file under test inside an anonymous namespace (which
       
    29 // prevents linking conflicts) with the mocked symbols redefined.
       
    30 
       
    31 // The include list should mirror the one found in the included source file -
       
    32 // with the ones that should pick up the mocks removed. Those should be included
       
    33 // later after the mocks have been defined.
       
    34 
       
    35 #include "logging/log.hpp"
       
    36 #include "jfr/jfrEvents.hpp"
       
    37 #include "jfr/metadata/jfrSerializer.hpp"
       
    38 #include "jfr/periodic/jfrOSInterface.hpp"
       
    39 #include "jfr/utilities/jfrTime.hpp"
       
    40 #include "jfr/utilities/jfrTypes.hpp"
       
    41 #include "runtime/os_perf.hpp"
       
    42 #include "utilities/globalDefinitions.hpp"
       
    43 #include "utilities/growableArray.hpp"
       
    44 
       
    45 #include "unittest.hpp"
       
    46 
       
    47 #include <vector>
       
    48 #include <list>
       
    49 #include <map>
       
    50 
       
    51 namespace {
       
    52 
       
    53   class MockFastUnorderedElapsedCounterSource : public ::FastUnorderedElapsedCounterSource {
       
    54   public:
       
    55     static jlong current_ticks;
       
    56     static Type now() {
       
    57       return current_ticks;
       
    58     }
       
    59     static uint64_t nanoseconds(Type value) {
       
    60       return value;
       
    61     }
       
    62   };
       
    63 
       
    64   typedef TimeInstant<CounterRepresentation, MockFastUnorderedElapsedCounterSource> JfrTicks;
       
    65   typedef TimeInterval<CounterRepresentation, MockFastUnorderedElapsedCounterSource> JfrTickspan;
       
    66 
       
    67   class MockJfrCheckpointWriter {
       
    68   public:
       
    69     traceid current;
       
    70     std::map<traceid, std::string> ids;
       
    71 
       
    72     const JfrCheckpointContext context() const {
       
    73       return JfrCheckpointContext();
       
    74     }
       
    75     intptr_t reserve(size_t size) {
       
    76       return 0;
       
    77     }
       
    78     void write_key(traceid id) {
       
    79       current = id;
       
    80     }
       
    81     void write(const char* data) {
       
    82       ids[current] = data;
       
    83     }
       
    84     void set_context(const JfrCheckpointContext ctx) { }
       
    85     void write_count(u4 nof_entries, jlong offset) { }
       
    86   };
       
    87 
       
    88   class MockJfrSerializer {
       
    89   public:
       
    90     static MockJfrSerializer* current;
       
    91 
       
    92     static bool register_serializer(JfrTypeId id, bool require_safepoint, bool permit_cache, MockJfrSerializer* serializer) {
       
    93       current = serializer;
       
    94       return true;
       
    95     }
       
    96 
       
    97     virtual void serialize(MockJfrCheckpointWriter& writer) = 0;
       
    98   };
       
    99 
       
   100   MockJfrSerializer* MockJfrSerializer::current;
       
   101 
       
   102   class MockEventNetworkUtilization : public ::EventNetworkUtilization
       
   103   {
       
   104   public:
       
   105     std::string iface;
       
   106     s8 readRate;
       
   107     s8 writeRate;
       
   108     static std::vector<MockEventNetworkUtilization> committed;
       
   109     MockJfrCheckpointWriter writer;
       
   110 
       
   111   public:
       
   112     MockEventNetworkUtilization(EventStartTime timing=TIMED) :
       
   113     ::EventNetworkUtilization(timing) {
       
   114     }
       
   115 
       
   116     void set_networkInterface(traceid new_value) {
       
   117       MockJfrSerializer::current->serialize(writer);
       
   118       iface = writer.ids[new_value];
       
   119     }
       
   120     void set_readRate(s8 new_value) {
       
   121       readRate = new_value;
       
   122     }
       
   123     void set_writeRate(s8 new_value) {
       
   124       writeRate = new_value;
       
   125     }
       
   126 
       
   127     void commit() {
       
   128       committed.push_back(*this);
       
   129     }
       
   130 
       
   131     void set_starttime(const JfrTicks& time) {}
       
   132 
       
   133     void set_endtime(const JfrTicks& time) {}
       
   134 
       
   135     static const MockEventNetworkUtilization& get_committed(const std::string& name) {
       
   136       static MockEventNetworkUtilization placeholder;
       
   137       for (std::vector<MockEventNetworkUtilization>::const_iterator i = committed.begin();
       
   138            i != committed.end();
       
   139            ++i) {
       
   140         if (name == i->iface) {
       
   141           return *i;
       
   142         }
       
   143       }
       
   144       return placeholder;
       
   145     }
       
   146   };
       
   147 
       
   148   std::vector<MockEventNetworkUtilization> MockEventNetworkUtilization::committed;
       
   149 
       
   150   jlong MockFastUnorderedElapsedCounterSource::current_ticks;
       
   151 
       
   152   struct MockNetworkInterface {
       
   153     std::string name;
       
   154     uint64_t bytes_in;
       
   155     uint64_t bytes_out;
       
   156     MockNetworkInterface(std::string name, uint64_t bytes_in, uint64_t bytes_out)
       
   157     : name(name),
       
   158     bytes_in(bytes_in),
       
   159     bytes_out(bytes_out) {
       
   160 
       
   161     }
       
   162     bool operator==(const MockNetworkInterface& rhs) const {
       
   163       return name == rhs.name;
       
   164     }
       
   165   };
       
   166 
       
   167   class NetworkInterface : public ::NetworkInterface {
       
   168   public:
       
   169     NetworkInterface(const char* name, uint64_t bytes_in, uint64_t bytes_out, NetworkInterface* next)
       
   170     : ::NetworkInterface(name, bytes_in, bytes_out, next) {
       
   171     }
       
   172     NetworkInterface* next(void) const {
       
   173       return reinterpret_cast<NetworkInterface*>(::NetworkInterface::next());
       
   174     }
       
   175   };
       
   176 
       
   177   class MockJfrOSInterface {
       
   178     static std::list<MockNetworkInterface> _interfaces;
       
   179 
       
   180   public:
       
   181     MockJfrOSInterface() {
       
   182     }
       
   183     static int network_utilization(NetworkInterface** network_interfaces) {
       
   184       *network_interfaces = NULL;
       
   185       for (std::list<MockNetworkInterface>::const_iterator i = _interfaces.begin();
       
   186            i != _interfaces.end();
       
   187            ++i) {
       
   188         NetworkInterface* cur = new NetworkInterface(i->name.c_str(), i->bytes_in, i->bytes_out, *network_interfaces);
       
   189         *network_interfaces = cur;
       
   190       }
       
   191       return OS_OK;
       
   192     }
       
   193     static MockNetworkInterface& add_interface(const std::string& name) {
       
   194       MockNetworkInterface iface(name, 0, 0);
       
   195       _interfaces.push_back(iface);
       
   196       return _interfaces.back();
       
   197     }
       
   198     static void remove_interface(const MockNetworkInterface& iface) {
       
   199       _interfaces.remove(iface);
       
   200     }
       
   201     static void clear_interfaces() {
       
   202       _interfaces.clear();
       
   203     }
       
   204   };
       
   205 
       
   206   std::list<MockNetworkInterface> MockJfrOSInterface::_interfaces;
       
   207 
       
   208 // Reincluding source files in the anonymous namespace unfortunately seems to
       
   209 // behave strangely with precompiled headers (only when using gcc though)
       
   210 #ifndef DONT_USE_PRECOMPILED_HEADER
       
   211 #define DONT_USE_PRECOMPILED_HEADER
       
   212 #endif
       
   213 
       
   214 #define EventNetworkUtilization MockEventNetworkUtilization
       
   215 #define FastUnorderedElapsedCounterSource MockFastUnorderedElapsedCounterSource
       
   216 #define JfrOSInterface MockJfrOSInterface
       
   217 #define JfrSerializer MockJfrSerializer
       
   218 #define JfrCheckpointWriter MockJfrCheckpointWriter
       
   219 
       
   220 #include "jfr/periodic/jfrNetworkUtilization.hpp"
       
   221 #include "jfr/periodic/jfrNetworkUtilization.cpp"
       
   222 
       
   223 #undef EventNetworkUtilization
       
   224 #undef FastUnorderedElapsedCounterSource
       
   225 #undef JfrOSInterface
       
   226 #undef JfrSerializer
       
   227 #undef JfrCheckpointWriter
       
   228 
       
   229 } // anonymous namespace
       
   230 
       
   231 class JfrTestNetworkUtilization : public ::testing::Test {
       
   232 protected:
       
   233   void SetUp() {
       
   234     MockEventNetworkUtilization::committed.clear();
       
   235     MockJfrOSInterface::clear_interfaces();
       
   236     // Ensure that tests are separated in time
       
   237     MockFastUnorderedElapsedCounterSource::current_ticks += 1 * NANOSECS_PER_SEC;
       
   238   }
       
   239 
       
   240   void TearDown() {
       
   241     JfrNetworkUtilization::destroy();
       
   242   }
       
   243 };
       
   244 
       
   245 TEST_VM_F(JfrTestNetworkUtilization, RequestFunctionBasic) {
       
   246 
       
   247   MockNetworkInterface& eth0 = MockJfrOSInterface::add_interface("eth0");
       
   248   JfrNetworkUtilization::send_events();
       
   249   ASSERT_EQ(0u, MockEventNetworkUtilization::committed.size());
       
   250 
       
   251   eth0.bytes_in += 10;
       
   252   MockFastUnorderedElapsedCounterSource::current_ticks += 2 * NANOSECS_PER_SEC;
       
   253 
       
   254   JfrNetworkUtilization::send_events();
       
   255   ASSERT_EQ(1u, MockEventNetworkUtilization::committed.size());
       
   256   MockEventNetworkUtilization& e = MockEventNetworkUtilization::committed[0];
       
   257   EXPECT_EQ(5, e.readRate);
       
   258   EXPECT_EQ(0, e.writeRate);
       
   259   EXPECT_STREQ("eth0", e.iface.c_str());
       
   260 }
       
   261 
       
   262 TEST_VM_F(JfrTestNetworkUtilization, RequestFunctionMultiple) {
       
   263 
       
   264   MockNetworkInterface& eth0 = MockJfrOSInterface::add_interface("eth0");
       
   265   MockNetworkInterface& eth1 = MockJfrOSInterface::add_interface("eth1");
       
   266   MockNetworkInterface& ppp0 = MockJfrOSInterface::add_interface("ppp0");
       
   267   JfrNetworkUtilization::send_events();
       
   268   ASSERT_EQ(0u, MockEventNetworkUtilization::committed.size());
       
   269 
       
   270   eth0.bytes_in += 10;
       
   271   eth1.bytes_in += 100;
       
   272   ppp0.bytes_out += 50;
       
   273   MockFastUnorderedElapsedCounterSource::current_ticks += 2 * NANOSECS_PER_SEC;
       
   274 
       
   275   JfrNetworkUtilization::send_events();
       
   276   ASSERT_EQ(3u, MockEventNetworkUtilization::committed.size());
       
   277   const MockEventNetworkUtilization& eth0_event = MockEventNetworkUtilization::get_committed("eth0");
       
   278   const MockEventNetworkUtilization& eth1_event = MockEventNetworkUtilization::get_committed("eth1");
       
   279   const MockEventNetworkUtilization& ppp0_event = MockEventNetworkUtilization::get_committed("ppp0");
       
   280 
       
   281   EXPECT_EQ(5, eth0_event.readRate);
       
   282   EXPECT_EQ(0, eth0_event.writeRate);
       
   283   EXPECT_STREQ("eth0", eth0_event.iface.c_str());
       
   284 
       
   285   EXPECT_EQ(50, eth1_event.readRate);
       
   286   EXPECT_EQ(0, eth1_event.writeRate);
       
   287   EXPECT_STREQ("eth1", eth1_event.iface.c_str());
       
   288 
       
   289   EXPECT_EQ(0, ppp0_event.readRate);
       
   290   EXPECT_EQ(25, ppp0_event.writeRate);
       
   291   EXPECT_STREQ("ppp0", ppp0_event.iface.c_str());
       
   292 }
       
   293 
       
   294 TEST_VM_F(JfrTestNetworkUtilization, InterfaceRemoved) {
       
   295   MockNetworkInterface& eth0 = MockJfrOSInterface::add_interface("eth0");
       
   296   MockNetworkInterface& eth1 = MockJfrOSInterface::add_interface("eth1");
       
   297   JfrNetworkUtilization::send_events();
       
   298   ASSERT_EQ(0u, MockEventNetworkUtilization::committed.size());
       
   299 
       
   300   eth0.bytes_in += 10;
       
   301   eth1.bytes_in += 20;
       
   302   MockFastUnorderedElapsedCounterSource::current_ticks += 2 * NANOSECS_PER_SEC;
       
   303 
       
   304   JfrNetworkUtilization::send_events();
       
   305   ASSERT_EQ(2u, MockEventNetworkUtilization::committed.size());
       
   306   const MockEventNetworkUtilization& eth0_event = MockEventNetworkUtilization::get_committed("eth0");
       
   307   const MockEventNetworkUtilization& eth1_event = MockEventNetworkUtilization::get_committed("eth1");
       
   308 
       
   309   EXPECT_EQ(5, eth0_event.readRate);
       
   310   EXPECT_EQ(0, eth0_event.writeRate);
       
   311   EXPECT_STREQ("eth0", eth0_event.iface.c_str());
       
   312 
       
   313   EXPECT_EQ(10, eth1_event.readRate);
       
   314   EXPECT_EQ(0, eth1_event.writeRate);
       
   315   EXPECT_STREQ("eth1", eth1_event.iface.c_str());
       
   316 
       
   317   MockJfrOSInterface::remove_interface(eth0);
       
   318   MockEventNetworkUtilization::committed.clear();
       
   319 
       
   320   eth1.bytes_in += 10;
       
   321   MockFastUnorderedElapsedCounterSource::current_ticks += 2 * NANOSECS_PER_SEC;
       
   322   JfrNetworkUtilization::send_events();
       
   323   ASSERT_EQ(1u, MockEventNetworkUtilization::committed.size());
       
   324   const MockEventNetworkUtilization& eth1_event_v2 = MockEventNetworkUtilization::get_committed("eth1");
       
   325 
       
   326   EXPECT_EQ(5, eth1_event_v2.readRate);
       
   327   EXPECT_EQ(0, eth1_event_v2.writeRate);
       
   328   EXPECT_STREQ("eth1", eth1_event_v2.iface.c_str());
       
   329 }
       
   330 
       
   331 TEST_VM_F(JfrTestNetworkUtilization, InterfaceReset) {
       
   332   MockNetworkInterface& eth0 = MockJfrOSInterface::add_interface("eth0");
       
   333   JfrNetworkUtilization::send_events();
       
   334   ASSERT_EQ(0u, MockEventNetworkUtilization::committed.size());
       
   335 
       
   336   eth0.bytes_in += 10;
       
   337   MockFastUnorderedElapsedCounterSource::current_ticks += 2 * NANOSECS_PER_SEC;
       
   338 
       
   339   JfrNetworkUtilization::send_events();
       
   340   ASSERT_EQ(1u, MockEventNetworkUtilization::committed.size());
       
   341   const MockEventNetworkUtilization& event = MockEventNetworkUtilization::committed[0];
       
   342   EXPECT_EQ(5, event.readRate);
       
   343   EXPECT_EQ(0, event.writeRate);
       
   344   EXPECT_STREQ("eth0", event.iface.c_str());
       
   345 
       
   346   eth0.bytes_in = 0;
       
   347   MockFastUnorderedElapsedCounterSource::current_ticks += 2 * NANOSECS_PER_SEC;
       
   348   MockEventNetworkUtilization::committed.clear();
       
   349 
       
   350   JfrNetworkUtilization::send_events();
       
   351   ASSERT_EQ(0u, MockEventNetworkUtilization::committed.size());
       
   352 
       
   353   eth0.bytes_in = 10;
       
   354   MockFastUnorderedElapsedCounterSource::current_ticks += 2 * NANOSECS_PER_SEC;
       
   355 
       
   356   JfrNetworkUtilization::send_events();
       
   357   ASSERT_EQ(1u, MockEventNetworkUtilization::committed.size());
       
   358   const MockEventNetworkUtilization& event_v2 = MockEventNetworkUtilization::committed[0];
       
   359   EXPECT_EQ(5, event_v2.readRate);
       
   360   EXPECT_EQ(0, event_v2.writeRate);
       
   361   EXPECT_STREQ("eth0", event_v2.iface.c_str());
       
   362 }