123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- // Copyright 2017 The Crashpad Authors. All rights reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- #include "client/annotation.h"
- #include <string>
- #include <vector>
- #include "base/rand_util.h"
- #include "client/crashpad_info.h"
- #include "gtest/gtest.h"
- #include "util/misc/clock.h"
- #include "util/thread/thread.h"
- namespace crashpad {
- namespace test {
- namespace {
- TEST(AnnotationListStatic, Register) {
- ASSERT_FALSE(AnnotationList::Get());
- EXPECT_TRUE(AnnotationList::Register());
- EXPECT_TRUE(AnnotationList::Get());
- EXPECT_EQ(AnnotationList::Get(), AnnotationList::Register());
- // This isn't expected usage of the AnnotationList API, but it is necessary
- // for testing.
- AnnotationList* list = AnnotationList::Get();
- CrashpadInfo::GetCrashpadInfo()->set_annotations_list(nullptr);
- delete list;
- EXPECT_FALSE(AnnotationList::Get());
- }
- class AnnotationList : public testing::Test {
- public:
- void SetUp() override {
- CrashpadInfo::GetCrashpadInfo()->set_annotations_list(&annotations_);
- }
- void TearDown() override {
- CrashpadInfo::GetCrashpadInfo()->set_annotations_list(nullptr);
- }
- // NOTE: Annotations should be declared at file-scope, but in order to test
- // them, they are declared as part of the test. These members are public so
- // they are accessible from global helpers.
- crashpad::StringAnnotation<8> one_{"First"};
- crashpad::StringAnnotation<256> two_{"Second"};
- crashpad::StringAnnotation<101> three_{"First"};
- protected:
- using AllAnnotations = std::vector<std::pair<std::string, std::string>>;
- AllAnnotations CollectAnnotations() {
- AllAnnotations annotations;
- for (Annotation* curr : annotations_) {
- if (!curr->is_set())
- continue;
- std::string value(static_cast<const char*>(curr->value()), curr->size());
- annotations.push_back(std::make_pair(curr->name(), value));
- }
- return annotations;
- }
- bool ContainsNameValue(const AllAnnotations& annotations,
- const std::string& name,
- const std::string& value) {
- return std::find(annotations.begin(),
- annotations.end(),
- std::make_pair(name, value)) != annotations.end();
- }
- crashpad::AnnotationList annotations_;
- };
- TEST_F(AnnotationList, SetAndClear) {
- one_.Set("this is a value longer than 8 bytes");
- AllAnnotations annotations = CollectAnnotations();
- EXPECT_EQ(1u, annotations.size());
- EXPECT_TRUE(ContainsNameValue(annotations, "First", "this is "));
- one_.Clear();
- EXPECT_EQ(0u, CollectAnnotations().size());
- one_.Set("short");
- two_.Set(std::string(500, 'A').data());
- annotations = CollectAnnotations();
- EXPECT_EQ(2u, annotations.size());
- EXPECT_EQ(5u, one_.size());
- EXPECT_EQ(256u, two_.size());
- EXPECT_TRUE(ContainsNameValue(annotations, "First", "short"));
- EXPECT_TRUE(ContainsNameValue(annotations, "Second", std::string(256, 'A')));
- }
- TEST_F(AnnotationList, DuplicateKeys) {
- ASSERT_EQ(0u, CollectAnnotations().size());
- one_.Set("1");
- three_.Set("2");
- AllAnnotations annotations = CollectAnnotations();
- EXPECT_EQ(2u, annotations.size());
- EXPECT_TRUE(ContainsNameValue(annotations, "First", "1"));
- EXPECT_TRUE(ContainsNameValue(annotations, "First", "2"));
- one_.Clear();
- annotations = CollectAnnotations();
- EXPECT_EQ(1u, annotations.size());
- }
- class RaceThread : public Thread {
- public:
- explicit RaceThread(test::AnnotationList* test) : Thread(), test_(test) {}
- private:
- void ThreadMain() override {
- for (int i = 0; i <= 50; ++i) {
- if (i % 2 == 0) {
- test_->three_.Set("three");
- test_->two_.Clear();
- } else {
- test_->three_.Clear();
- }
- SleepNanoseconds(base::RandInt(1, 1000));
- }
- }
- test::AnnotationList* test_;
- };
- TEST_F(AnnotationList, MultipleThreads) {
- ASSERT_EQ(0u, CollectAnnotations().size());
- RaceThread other_thread(this);
- other_thread.Start();
- for (int i = 0; i <= 50; ++i) {
- if (i % 2 == 0) {
- one_.Set("one");
- two_.Set("two");
- } else {
- one_.Clear();
- }
- SleepNanoseconds(base::RandInt(1, 1000));
- }
- other_thread.Join();
- AllAnnotations annotations = CollectAnnotations();
- EXPECT_GE(annotations.size(), 2u);
- EXPECT_LE(annotations.size(), 3u);
- EXPECT_TRUE(ContainsNameValue(annotations, "First", "one"));
- EXPECT_TRUE(ContainsNameValue(annotations, "First", "three"));
- if (annotations.size() == 3) {
- EXPECT_TRUE(ContainsNameValue(annotations, "Second", "two"));
- }
- }
- } // namespace
- } // namespace test
- } // namespace crashpad
|