blob: cf4843c2c3ae76b2baceb1fd759254506319470e [file] [log] [blame]
Isabelle Taylorda551622018-07-17 11:48:53 +01001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "src/trace_processor/thread_table.h"
18#include "src/trace_processor/process_table.h"
Isabelle Taylora0a22972018-08-03 12:06:12 +010019#include "src/trace_processor/process_tracker.h"
Primiano Tucci0d72a312018-08-07 14:42:45 +010020#include "src/trace_processor/proto_trace_parser.h"
Isabelle Taylora0a22972018-08-03 12:06:12 +010021#include "src/trace_processor/sched_tracker.h"
Isabelle Taylorda551622018-07-17 11:48:53 +010022#include "src/trace_processor/scoped_db.h"
Isabelle Taylora0a22972018-08-03 12:06:12 +010023#include "src/trace_processor/trace_processor_context.h"
Isabelle Taylorda551622018-07-17 11:48:53 +010024
25#include "gmock/gmock.h"
26#include "gtest/gtest.h"
27
28namespace perfetto {
29namespace trace_processor {
30namespace {
31
32class ThreadTableUnittest : public ::testing::Test {
33 public:
34 ThreadTableUnittest() {
35 sqlite3* db = nullptr;
36 PERFETTO_CHECK(sqlite3_open(":memory:", &db) == SQLITE_OK);
37 db_.reset(db);
38
Isabelle Taylora0a22972018-08-03 12:06:12 +010039 context_.storage.reset(new TraceStorage());
40 context_.process_tracker.reset(new ProcessTracker(&context_));
41 context_.sched_tracker.reset(new SchedTracker(&context_));
42
43 ThreadTable::RegisterTable(db_.get(), context_.storage.get());
44 ProcessTable::RegisterTable(db_.get(), context_.storage.get());
Isabelle Taylorda551622018-07-17 11:48:53 +010045 }
46
47 void PrepareValidStatement(const std::string& sql) {
48 int size = static_cast<int>(sql.size());
49 sqlite3_stmt* stmt;
50 ASSERT_EQ(sqlite3_prepare_v2(*db_, sql.c_str(), size, &stmt, nullptr),
51 SQLITE_OK);
52 stmt_.reset(stmt);
53 }
54
55 const char* GetColumnAsText(int colId) {
56 return reinterpret_cast<const char*>(sqlite3_column_text(*stmt_, colId));
57 }
58
Isabelle Taylora0a22972018-08-03 12:06:12 +010059 ~ThreadTableUnittest() override { context_.storage->ResetStorage(); }
60
Isabelle Taylorda551622018-07-17 11:48:53 +010061 protected:
Isabelle Taylora0a22972018-08-03 12:06:12 +010062 TraceProcessorContext context_;
Isabelle Taylorda551622018-07-17 11:48:53 +010063 ScopedDb db_;
64 ScopedStmt stmt_;
65};
66
67TEST_F(ThreadTableUnittest, Select) {
68 uint32_t cpu = 3;
69 uint64_t timestamp = 100;
Isabelle Taylorda551622018-07-17 11:48:53 +010070 uint32_t prev_state = 32;
Primiano Tuccifbc1f602018-08-08 18:23:32 +010071 static const char kThreadName1[] = "thread1";
72 static const char kThreadName2[] = "thread2";
Isabelle Taylorda551622018-07-17 11:48:53 +010073
Primiano Tuccib75dcee2018-08-08 12:21:36 +010074 context_.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1, prev_state,
Primiano Tucci2da5d2e2018-08-10 14:23:31 +010075 kThreadName1, /*tid=*/4);
Primiano Tuccib75dcee2018-08-08 12:21:36 +010076 context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4,
Primiano Tucci2da5d2e2018-08-10 14:23:31 +010077 prev_state, kThreadName2, /*tid=*/1);
Isabelle Taylorda551622018-07-17 11:48:53 +010078
Primiano Tucci2da5d2e2018-08-10 14:23:31 +010079 context_.process_tracker->UpdateProcess(2, "test");
Primiano Tuccib75dcee2018-08-08 12:21:36 +010080 context_.process_tracker->UpdateThread(4 /*tid*/, 2 /*pid*/);
Primiano Tuccifbc1f602018-08-08 18:23:32 +010081 PrepareValidStatement("SELECT utid, upid, tid, name FROM thread where tid=4");
Isabelle Taylorda551622018-07-17 11:48:53 +010082
83 ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
84 ASSERT_EQ(sqlite3_column_int(*stmt_, 0), 1 /* utid */);
85 ASSERT_EQ(sqlite3_column_int(*stmt_, 1), 1 /* upid */);
Primiano Tuccib75dcee2018-08-08 12:21:36 +010086 ASSERT_EQ(sqlite3_column_int(*stmt_, 2), 4 /* tid */);
Primiano Tuccifbc1f602018-08-08 18:23:32 +010087 ASSERT_STREQ(GetColumnAsText(3), kThreadName2);
Isabelle Taylorda551622018-07-17 11:48:53 +010088
89 ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
90}
91
92TEST_F(ThreadTableUnittest, SelectWhere) {
93 uint32_t cpu = 3;
94 uint64_t timestamp = 100;
Isabelle Taylorda551622018-07-17 11:48:53 +010095 uint32_t prev_state = 32;
Primiano Tuccifbc1f602018-08-08 18:23:32 +010096 static const char kThreadName1[] = "thread1";
97 static const char kThreadName2[] = "thread2";
Isabelle Taylorda551622018-07-17 11:48:53 +010098
Primiano Tuccib75dcee2018-08-08 12:21:36 +010099 context_.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1, prev_state,
Primiano Tuccifbc1f602018-08-08 18:23:32 +0100100 kThreadName1,
Primiano Tuccib75dcee2018-08-08 12:21:36 +0100101 /*tid=*/4);
102 context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4,
Primiano Tuccifbc1f602018-08-08 18:23:32 +0100103 prev_state, kThreadName2,
Primiano Tuccib75dcee2018-08-08 12:21:36 +0100104 /*tid=*/1);
105 context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 2, /*tid=*/1,
Primiano Tucci2da5d2e2018-08-10 14:23:31 +0100106 prev_state, kThreadName1, /*tid=*/4);
Isabelle Taylorda551622018-07-17 11:48:53 +0100107
Primiano Tucci2da5d2e2018-08-10 14:23:31 +0100108 context_.process_tracker->UpdateProcess(2, "test");
Primiano Tuccib75dcee2018-08-08 12:21:36 +0100109 context_.process_tracker->UpdateThread(4 /*tid*/, 2 /*pid*/);
110 context_.process_tracker->UpdateThread(1 /*tid*/, 2 /*pid*/);
111 PrepareValidStatement(
112 "SELECT utid, upid, tid, name FROM thread where tid = 4");
Isabelle Taylorda551622018-07-17 11:48:53 +0100113
114 ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
115 ASSERT_EQ(sqlite3_column_int(*stmt_, 0), 1 /* utid */);
116 ASSERT_EQ(sqlite3_column_int(*stmt_, 1), 1 /* upid */);
Primiano Tuccib75dcee2018-08-08 12:21:36 +0100117 ASSERT_EQ(sqlite3_column_int(*stmt_, 2), 4 /* tid */);
Primiano Tuccifbc1f602018-08-08 18:23:32 +0100118 ASSERT_STREQ(GetColumnAsText(3), kThreadName2);
Isabelle Taylorda551622018-07-17 11:48:53 +0100119
120 ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
121}
122
123TEST_F(ThreadTableUnittest, JoinWithProcess) {
124 uint32_t cpu = 3;
125 uint64_t timestamp = 100;
Isabelle Taylorda551622018-07-17 11:48:53 +0100126 uint32_t prev_state = 32;
Primiano Tuccifbc1f602018-08-08 18:23:32 +0100127 static const char kThreadName1[] = "thread1";
128 static const char kThreadName2[] = "thread2";
Isabelle Taylorda551622018-07-17 11:48:53 +0100129
Primiano Tuccib75dcee2018-08-08 12:21:36 +0100130 context_.sched_tracker->PushSchedSwitch(cpu, timestamp, /*tid=*/1, prev_state,
Primiano Tuccifbc1f602018-08-08 18:23:32 +0100131 kThreadName1,
Primiano Tucci2da5d2e2018-08-10 14:23:31 +0100132
Primiano Tuccib75dcee2018-08-08 12:21:36 +0100133 /*tid=*/4);
134 context_.sched_tracker->PushSchedSwitch(cpu, timestamp + 1, /*tid=*/4,
Primiano Tuccifbc1f602018-08-08 18:23:32 +0100135 prev_state, kThreadName2,
Primiano Tucci2da5d2e2018-08-10 14:23:31 +0100136
Primiano Tuccib75dcee2018-08-08 12:21:36 +0100137 /*tid=*/1);
Isabelle Taylorda551622018-07-17 11:48:53 +0100138
Primiano Tuccib75dcee2018-08-08 12:21:36 +0100139 // Also create a process for which we haven't seen any thread.
Primiano Tucci2da5d2e2018-08-10 14:23:31 +0100140 context_.process_tracker->UpdateProcess(7, "pid7");
Primiano Tuccib75dcee2018-08-08 12:21:36 +0100141
Primiano Tucci2da5d2e2018-08-10 14:23:31 +0100142 context_.process_tracker->UpdateProcess(2, "pid2");
Primiano Tuccifbc1f602018-08-08 18:23:32 +0100143 context_.process_tracker->UpdateThread(/*tid=*/4, /*pid=*/2);
Primiano Tuccib75dcee2018-08-08 12:21:36 +0100144
Isabelle Taylorda551622018-07-17 11:48:53 +0100145 PrepareValidStatement(
Primiano Tuccib75dcee2018-08-08 12:21:36 +0100146 "SELECT utid, thread.tid, thread.name, process.upid, process.pid, "
Primiano Tuccifbc1f602018-08-08 18:23:32 +0100147 "process.name FROM thread INNER JOIN process USING (upid) WHERE pid = 2 "
148 "ORDER BY tid");
Isabelle Taylorda551622018-07-17 11:48:53 +0100149
Primiano Tuccifbc1f602018-08-08 18:23:32 +0100150 // At this point we should see two threads bound to process with pid=2:
151
152 // (1) The (implicitly created) main thread (tid=pid=2).
Isabelle Taylorda551622018-07-17 11:48:53 +0100153 ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
Primiano Tuccifbc1f602018-08-08 18:23:32 +0100154 auto utid_for_tid2 = sqlite3_column_int(*stmt_, 0);
155 ASSERT_GT(utid_for_tid2, 0);
156 ASSERT_EQ(sqlite3_column_int(*stmt_, 1), 2 /* tid */);
Primiano Tuccib75dcee2018-08-08 12:21:36 +0100157 ASSERT_EQ(sqlite3_column_int(*stmt_, 4), 2 /* pid */);
Primiano Tuccifbc1f602018-08-08 18:23:32 +0100158 ASSERT_EQ(sqlite3_column_int(*stmt_, 3), 2 /* upid */);
159 ASSERT_STREQ(GetColumnAsText(2), ""); // No name seen for main thread.
160 ASSERT_STREQ(GetColumnAsText(5), "pid2");
161
162 // (2) A thread with tid=4.
163 ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
164 auto utid_for_tid4 = sqlite3_column_int(*stmt_, 0);
165 ASSERT_GT(utid_for_tid4, 0);
166 ASSERT_NE(utid_for_tid4, utid_for_tid2);
167 ASSERT_EQ(sqlite3_column_int(*stmt_, 1), 4 /* tid */);
168 ASSERT_EQ(sqlite3_column_int(*stmt_, 4), 2 /* pid */);
169 ASSERT_EQ(sqlite3_column_int(*stmt_, 3), 2 /* upid */);
170 ASSERT_STREQ(GetColumnAsText(2), kThreadName2);
171 ASSERT_STREQ(GetColumnAsText(5), "pid2");
Isabelle Taylorda551622018-07-17 11:48:53 +0100172
173 ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
174}
175
176} // namespace
177} // namespace trace_processor
178} // namespace perfetto