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 139 140 141
|
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/metrics/system_session_analyzer/system_session_analyzer_win.h"
#include <algorithm>
#include <utility>
#include <vector>
#include "base/logging.h"
#include "base/time/time.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace metrics {
namespace {
const uint16_t kIdSessionStart = 6005U;
const uint16_t kIdSessionEnd = 6006U;
const uint16_t kIdSessionEndUnclean = 6008U;
} // namespace
// Ensure the fetcher retrieves events.
// Due to https://crbug.com/1053451 which is caused by a Windows "bug" tracked
// by https://crbug.com/1053451 this cannot be made reliable. Running
// browser_tests can and does generate so much event logging (DCOM events) that
// none of the looked for events remain.
TEST(SystemSessionAnalyzerTest, DISABLED_FetchEvents) {
SystemSessionAnalyzer analyzer(0);
std::vector<SystemSessionAnalyzer::EventInfo> events;
ASSERT_TRUE(analyzer.FetchEvents(1U, &events));
EXPECT_EQ(1U, events.size());
}
// Ensure the fetcher's retrieved events conform to our expectations.
// Note: this test fails if the host system doesn't have at least 1 prior
// session.
TEST(SystemSessionAnalyzerTest, ValidateEvents) {
SystemSessionAnalyzer analyzer(1U);
auto is_session_unclean = analyzer.IsSessionUnclean(base::Time::Now());
// If the system event log rate is high enough then there may not be enough
// events to make a clean/unclean determination. Check for this situation and
// don't treat it as a failure. See https://crbug.com/968440 and
// https://crbug.com/1053451 for details.
if (is_session_unclean == SystemSessionAnalyzer::INSUFFICIENT_DATA) {
// This warning can be ignored, but it does mean that our clean/unclean
// check did not give an answer.
LOG(WARNING) << "Insufficient events found in ValidateEvents.";
} else {
EXPECT_EQ(SystemSessionAnalyzer::CLEAN, is_session_unclean)
<< "Extended error code is: "
<< static_cast<int>(analyzer.GetExtendedFailureStatus());
}
}
// Stubs FetchEvents.
class StubSystemSessionAnalyzer : public SystemSessionAnalyzer {
public:
StubSystemSessionAnalyzer(uint32_t max_session_cnt)
: SystemSessionAnalyzer(max_session_cnt) {}
bool FetchEvents(size_t requested_events,
std::vector<EventInfo>* event_infos) override {
DCHECK(event_infos);
size_t num_to_copy = std::min(requested_events, events_.size());
if (num_to_copy) {
event_infos->clear();
event_infos->insert(event_infos->begin(), events_.begin(),
events_.begin() + num_to_copy);
events_.erase(events_.begin(), events_.begin() + num_to_copy);
}
return true;
}
void AddEvent(const EventInfo& info) { events_.push_back(info); }
private:
std::vector<EventInfo> events_;
};
TEST(SystemSessionAnalyzerTest, StandardCase) {
StubSystemSessionAnalyzer analyzer(2U);
base::Time time = base::Time::Now();
analyzer.AddEvent({kIdSessionStart, time});
analyzer.AddEvent({kIdSessionEndUnclean, time - base::Seconds(10)});
analyzer.AddEvent({kIdSessionStart, time - base::Seconds(20)});
analyzer.AddEvent({kIdSessionEnd, time - base::Seconds(22)});
analyzer.AddEvent({kIdSessionStart, time - base::Seconds(28)});
EXPECT_EQ(SystemSessionAnalyzer::OUTSIDE_RANGE,
analyzer.IsSessionUnclean(time - base::Seconds(30)));
EXPECT_EQ(SystemSessionAnalyzer::CLEAN,
analyzer.IsSessionUnclean(time - base::Seconds(25)));
EXPECT_EQ(SystemSessionAnalyzer::UNCLEAN,
analyzer.IsSessionUnclean(time - base::Seconds(20)));
EXPECT_EQ(SystemSessionAnalyzer::UNCLEAN,
analyzer.IsSessionUnclean(time - base::Seconds(15)));
EXPECT_EQ(SystemSessionAnalyzer::UNCLEAN,
analyzer.IsSessionUnclean(time - base::Seconds(10)));
EXPECT_EQ(SystemSessionAnalyzer::CLEAN,
analyzer.IsSessionUnclean(time - base::Seconds(5)));
EXPECT_EQ(SystemSessionAnalyzer::CLEAN,
analyzer.IsSessionUnclean(time + base::Seconds(5)));
}
TEST(SystemSessionAnalyzerTest, NoEvent) {
StubSystemSessionAnalyzer analyzer(0U);
EXPECT_EQ(SystemSessionAnalyzer::INSUFFICIENT_DATA,
analyzer.IsSessionUnclean(base::Time::Now()));
}
TEST(SystemSessionAnalyzerTest, TimeInversion) {
StubSystemSessionAnalyzer analyzer(1U);
base::Time time = base::Time::Now();
analyzer.AddEvent({kIdSessionStart, time});
analyzer.AddEvent({kIdSessionEnd, time + base::Seconds(1)});
analyzer.AddEvent({kIdSessionStart, time - base::Seconds(1)});
EXPECT_EQ(SystemSessionAnalyzer::INITIALIZE_FAILED,
analyzer.IsSessionUnclean(base::Time::Now()));
}
TEST(SystemSessionAnalyzerTest, IdInversion) {
StubSystemSessionAnalyzer analyzer(1U);
base::Time time = base::Time::Now();
analyzer.AddEvent({kIdSessionStart, time});
analyzer.AddEvent({kIdSessionStart, time - base::Seconds(1)});
analyzer.AddEvent({kIdSessionEnd, time - base::Seconds(2)});
EXPECT_EQ(SystemSessionAnalyzer::INITIALIZE_FAILED,
analyzer.IsSessionUnclean(base::Time::Now()));
}
} // namespace metrics
|