serialization_utils_unittest.cc 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/metrics/serialization/serialization_utils.h"
  5. #include <stddef.h>
  6. #include <stdint.h>
  7. #include "base/check.h"
  8. #include "base/files/file.h"
  9. #include "base/files/file_util.h"
  10. #include "base/files/scoped_temp_dir.h"
  11. #include "base/strings/stringprintf.h"
  12. #include "base/test/metrics/histogram_tester.h"
  13. #include "components/metrics/serialization/metric_sample.h"
  14. #include "testing/gmock/include/gmock/gmock.h"
  15. #include "testing/gtest/include/gtest/gtest.h"
  16. namespace metrics {
  17. namespace {
  18. using ::testing::IsEmpty;
  19. class SerializationUtilsTest : public testing::Test {
  20. protected:
  21. SerializationUtilsTest() {
  22. bool success = temporary_dir_.CreateUniqueTempDir();
  23. if (success) {
  24. base::FilePath dir_path = temporary_dir_.GetPath();
  25. filename_ = dir_path.value() + "chromeossampletest";
  26. filepath_ = base::FilePath(filename_);
  27. }
  28. }
  29. void SetUp() override { base::DeleteFile(filepath_); }
  30. void TestSerialization(MetricSample* sample) {
  31. std::string serialized(sample->ToString());
  32. ASSERT_EQ('\0', serialized.back());
  33. std::unique_ptr<MetricSample> deserialized =
  34. SerializationUtils::ParseSample(serialized);
  35. ASSERT_TRUE(deserialized);
  36. EXPECT_TRUE(sample->IsEqual(*deserialized.get()));
  37. }
  38. const std::string& filename() const { return filename_; }
  39. const base::FilePath& filepath() const { return filepath_; }
  40. private:
  41. std::string filename_;
  42. base::ScopedTempDir temporary_dir_;
  43. base::FilePath filepath_;
  44. };
  45. TEST_F(SerializationUtilsTest, CrashSerializeTest) {
  46. TestSerialization(MetricSample::CrashSample("test").get());
  47. }
  48. TEST_F(SerializationUtilsTest, HistogramSerializeTest) {
  49. TestSerialization(
  50. MetricSample::HistogramSample("myhist", 13, 1, 100, 10).get());
  51. }
  52. TEST_F(SerializationUtilsTest, LinearSerializeTest) {
  53. TestSerialization(
  54. MetricSample::LinearHistogramSample("linearhist", 12, 30).get());
  55. }
  56. TEST_F(SerializationUtilsTest, SparseSerializeTest) {
  57. TestSerialization(MetricSample::SparseHistogramSample("mysparse", 30).get());
  58. }
  59. TEST_F(SerializationUtilsTest, UserActionSerializeTest) {
  60. TestSerialization(MetricSample::UserActionSample("myaction").get());
  61. }
  62. TEST_F(SerializationUtilsTest, IllegalNameAreFilteredTest) {
  63. std::unique_ptr<MetricSample> sample1 =
  64. MetricSample::SparseHistogramSample("no space", 10);
  65. std::unique_ptr<MetricSample> sample2 = MetricSample::LinearHistogramSample(
  66. base::StringPrintf("here%cbhe", '\0'), 1, 3);
  67. EXPECT_FALSE(
  68. SerializationUtils::WriteMetricToFile(*sample1.get(), filename()));
  69. EXPECT_FALSE(
  70. SerializationUtils::WriteMetricToFile(*sample2.get(), filename()));
  71. int64_t size = 0;
  72. ASSERT_TRUE(!PathExists(filepath()) || base::GetFileSize(filepath(), &size));
  73. EXPECT_EQ(0, size);
  74. }
  75. TEST_F(SerializationUtilsTest, BadInputIsCaughtTest) {
  76. std::string input(
  77. base::StringPrintf("sparsehistogram%cname foo%c", '\0', '\0'));
  78. EXPECT_EQ(nullptr, MetricSample::ParseSparseHistogram(input).get());
  79. }
  80. TEST_F(SerializationUtilsTest, MessageSeparatedByZero) {
  81. std::unique_ptr<MetricSample> crash = MetricSample::CrashSample("mycrash");
  82. SerializationUtils::WriteMetricToFile(*crash.get(), filename());
  83. int64_t size = 0;
  84. ASSERT_TRUE(base::GetFileSize(filepath(), &size));
  85. // 4 bytes for the size
  86. // 5 bytes for crash
  87. // 7 bytes for mycrash
  88. // 2 bytes for the \0
  89. // -> total of 18
  90. EXPECT_EQ(size, 18);
  91. }
  92. TEST_F(SerializationUtilsTest, MessagesTooLongAreDiscardedTest) {
  93. // Creates a message that is bigger than the maximum allowed size.
  94. // As we are adding extra character (crash, \0s, etc), if the name is
  95. // kMessageMaxLength long, it will be too long.
  96. std::string name(SerializationUtils::kMessageMaxLength, 'c');
  97. std::unique_ptr<MetricSample> crash = MetricSample::CrashSample(name);
  98. EXPECT_FALSE(SerializationUtils::WriteMetricToFile(*crash.get(), filename()));
  99. int64_t size = 0;
  100. ASSERT_TRUE(base::GetFileSize(filepath(), &size));
  101. EXPECT_EQ(0, size);
  102. }
  103. TEST_F(SerializationUtilsTest, ReadLongMessageTest) {
  104. base::File test_file(filepath(),
  105. base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_APPEND);
  106. std::string message(SerializationUtils::kMessageMaxLength + 1, 'c');
  107. int32_t message_size = message.length() + sizeof(int32_t);
  108. test_file.WriteAtCurrentPos(reinterpret_cast<const char*>(&message_size),
  109. sizeof(message_size));
  110. test_file.WriteAtCurrentPos(message.c_str(), message.length());
  111. test_file.Close();
  112. std::unique_ptr<MetricSample> crash = MetricSample::CrashSample("test");
  113. SerializationUtils::WriteMetricToFile(*crash.get(), filename());
  114. std::vector<std::unique_ptr<MetricSample>> samples;
  115. SerializationUtils::ReadAndTruncateMetricsFromFile(filename(), &samples);
  116. ASSERT_EQ(size_t(1), samples.size());
  117. ASSERT_TRUE(samples[0].get() != nullptr);
  118. EXPECT_TRUE(crash->IsEqual(*samples[0]));
  119. }
  120. TEST_F(SerializationUtilsTest, NegativeLengthTest) {
  121. // This input is specifically constructed to yield a single crash sample when
  122. // parsed by a buggy version of the code but fails to parse and doesn't yield
  123. // samples when parsed by a correct implementation.
  124. constexpr uint8_t kInput[] = {
  125. // Length indicating that next length field is the negative one below.
  126. // This sample is invalid as it contains more than three null bytes.
  127. 0x14,
  128. 0x00,
  129. 0x00,
  130. 0x00,
  131. // Encoding of a valid crash sample.
  132. 0x0c,
  133. 0x00,
  134. 0x00,
  135. 0x00,
  136. 0x63,
  137. 0x72,
  138. 0x61,
  139. 0x73,
  140. 0x68,
  141. 0x00,
  142. 0x61,
  143. 0x00,
  144. // Invalid sample that jumps past the negative length bytes below.
  145. 0x08,
  146. 0x00,
  147. 0x00,
  148. 0x00,
  149. // This is -16 in two's complement interpretation, pointing to the valid
  150. // crash sample before.
  151. 0xf0,
  152. 0xff,
  153. 0xff,
  154. 0xff,
  155. };
  156. CHECK(base::WriteFile(filepath(), reinterpret_cast<const char*>(kInput),
  157. sizeof(kInput)));
  158. std::vector<std::unique_ptr<MetricSample>> samples;
  159. SerializationUtils::ReadAndTruncateMetricsFromFile(filename(), &samples);
  160. ASSERT_EQ(0U, samples.size());
  161. }
  162. TEST_F(SerializationUtilsTest, WriteReadTest) {
  163. std::unique_ptr<MetricSample> hist =
  164. MetricSample::HistogramSample("myhist", 1, 2, 3, 4);
  165. std::unique_ptr<MetricSample> crash = MetricSample::CrashSample("mycrash");
  166. std::unique_ptr<MetricSample> lhist =
  167. MetricSample::LinearHistogramSample("linear", 1, 10);
  168. std::unique_ptr<MetricSample> shist =
  169. MetricSample::SparseHistogramSample("mysparse", 30);
  170. std::unique_ptr<MetricSample> action =
  171. MetricSample::UserActionSample("myaction");
  172. SerializationUtils::WriteMetricToFile(*hist.get(), filename());
  173. SerializationUtils::WriteMetricToFile(*crash.get(), filename());
  174. SerializationUtils::WriteMetricToFile(*lhist.get(), filename());
  175. SerializationUtils::WriteMetricToFile(*shist.get(), filename());
  176. SerializationUtils::WriteMetricToFile(*action.get(), filename());
  177. std::vector<std::unique_ptr<MetricSample>> vect;
  178. SerializationUtils::ReadAndTruncateMetricsFromFile(filename(), &vect);
  179. ASSERT_EQ(vect.size(), size_t(5));
  180. for (auto& sample : vect) {
  181. ASSERT_NE(nullptr, sample.get());
  182. }
  183. EXPECT_TRUE(hist->IsEqual(*vect[0]));
  184. EXPECT_TRUE(crash->IsEqual(*vect[1]));
  185. EXPECT_TRUE(lhist->IsEqual(*vect[2]));
  186. EXPECT_TRUE(shist->IsEqual(*vect[3]));
  187. EXPECT_TRUE(action->IsEqual(*vect[4]));
  188. int64_t size = 0;
  189. ASSERT_TRUE(base::GetFileSize(filepath(), &size));
  190. ASSERT_EQ(0, size);
  191. }
  192. TEST_F(SerializationUtilsTest, TooManyMessagesTest) {
  193. std::unique_ptr<MetricSample> hist =
  194. MetricSample::HistogramSample("myhist", 1, 2, 3, 4);
  195. constexpr int kDiscardedSamples = 50000;
  196. for (int i = 0;
  197. i < SerializationUtils::kMaxMessagesPerRead + kDiscardedSamples; i++) {
  198. SerializationUtils::WriteMetricToFile(*hist.get(), filename());
  199. }
  200. std::vector<std::unique_ptr<MetricSample>> vect;
  201. SerializationUtils::ReadAndTruncateMetricsFromFile(filename(), &vect);
  202. ASSERT_EQ(SerializationUtils::kMaxMessagesPerRead,
  203. static_cast<int>(vect.size()));
  204. for (auto& sample : vect) {
  205. ASSERT_NE(nullptr, sample.get());
  206. EXPECT_TRUE(hist->IsEqual(*sample));
  207. }
  208. int64_t size = 0;
  209. ASSERT_TRUE(base::GetFileSize(filepath(), &size));
  210. ASSERT_EQ(0, size);
  211. }
  212. TEST_F(SerializationUtilsTest, ReadEmptyFile) {
  213. {
  214. // Create a zero-length file and then close file descriptor.
  215. base::File file(filepath(),
  216. base::File::FLAG_CREATE | base::File::FLAG_WRITE);
  217. ASSERT_TRUE(file.IsValid());
  218. }
  219. std::vector<std::unique_ptr<MetricSample>> vect;
  220. SerializationUtils::ReadAndTruncateMetricsFromFile(filename(), &vect);
  221. EXPECT_THAT(vect, IsEmpty());
  222. }
  223. TEST_F(SerializationUtilsTest, ReadNonExistentFile) {
  224. base::DeleteFile(filepath()); // Ensure non-existance.
  225. base::HistogramTester histogram_tester;
  226. std::vector<std::unique_ptr<MetricSample>> vect;
  227. SerializationUtils::ReadAndTruncateMetricsFromFile(filename(), &vect);
  228. EXPECT_THAT(vect, IsEmpty());
  229. }
  230. } // namespace
  231. } // namespace metrics