Merge "perfetto: handle mock traces setting data about tid and tgid == 0"
diff --git a/src/trace_processor/process_table.cc b/src/trace_processor/process_table.cc
index 97bc205..a06ce2a 100644
--- a/src/trace_processor/process_table.cc
+++ b/src/trace_processor/process_table.cc
@@ -69,7 +69,7 @@
                              const QueryConstraints& qc,
                              sqlite3_value** argv)
     : storage_(storage) {
-  min = 1;
+  min = 0;
   max = static_cast<uint32_t>(storage_->process_count());
   desc = false;
   current = min;
diff --git a/src/trace_processor/process_table_unittest.cc b/src/trace_processor/process_table_unittest.cc
index 7012f87..44174a7 100644
--- a/src/trace_processor/process_table_unittest.cc
+++ b/src/trace_processor/process_table_unittest.cc
@@ -69,6 +69,9 @@
   PrepareValidStatement("SELECT upid, name FROM process");
 
   ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
+  ASSERT_EQ(sqlite3_column_int(*stmt_, 0), 0 /* upid */);
+
+  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
   ASSERT_EQ(sqlite3_column_int(*stmt_, 0), 1 /* upid */);
   ASSERT_STREQ(GetColumnAsText(1), kCommProc1);
 
@@ -110,6 +113,9 @@
   ASSERT_EQ(sqlite3_column_int(*stmt_, 0), 1 /* upid */);
   ASSERT_STREQ(GetColumnAsText(1), kCommProc1);
 
+  ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_ROW);
+  ASSERT_EQ(sqlite3_column_int(*stmt_, 0), 0 /* upid */);
+
   ASSERT_EQ(sqlite3_step(*stmt_), SQLITE_DONE);
 }
 
diff --git a/src/trace_processor/process_tracker.cc b/src/trace_processor/process_tracker.cc
index 2da8994..efb39e5 100644
--- a/src/trace_processor/process_tracker.cc
+++ b/src/trace_processor/process_tracker.cc
@@ -75,14 +75,15 @@
   for (auto it = tids_pair.first; it != tids_pair.second; it++) {
     UniqueTid iter_utid = it->second;
     auto* iter_thread = context_->storage->GetMutableThread(iter_utid);
-    if (iter_thread->upid == 0) {
+    if (!iter_thread->upid.has_value()) {
       // We haven't discovered the parent process for the thread. Assign it
       // now and use this thread.
       thread = iter_thread;
       utid = iter_utid;
       break;
     }
-    const auto& iter_process = context_->storage->GetProcess(iter_thread->upid);
+    const auto& iter_process =
+        context_->storage->GetProcess(iter_thread->upid.value());
     if (iter_process.pid == pid) {
       // We found a thread that matches both the tid and its parent pid.
       thread = iter_thread;
@@ -99,7 +100,7 @@
   }
 
   // Find matching process or create new one.
-  if (thread->upid == 0) {  // Not set, upid == 0 is invalid.
+  if (!thread->upid.has_value()) {
     std::tie(thread->upid, std::ignore) =
         GetOrCreateProcess(pid, thread->start_ns);
   }
@@ -129,15 +130,18 @@
 ProcessTracker::GetOrCreateProcess(uint32_t pid, uint64_t start_ns) {
   auto pids_pair = pids_.equal_range(pid);
 
-  UniquePid upid = 0;
+  base::Optional<UniquePid> found_upid;
   for (auto it = pids_pair.first; it != pids_pair.second; it++) {
     if (it->first == pid) {
-      upid = it->second;
+      found_upid = it->second;
       break;
     }
   }
 
-  if (upid == 0) {
+  UniquePid upid;
+  if (found_upid.has_value()) {
+    upid = found_upid.value();
+  } else {
     upid = context_->storage->AddEmptyProcess(pid);
     pids_.emplace(pid, upid);
   }
diff --git a/src/trace_processor/process_tracker_unittest.cc b/src/trace_processor/process_tracker_unittest.cc
index 40d4c26..c4742e2 100644
--- a/src/trace_processor/process_tracker_unittest.cc
+++ b/src/trace_processor/process_tracker_unittest.cc
@@ -88,7 +88,7 @@
   TraceStorage::Process process = context.storage->GetProcess(/*utid=*/1);
 
   ASSERT_EQ(thread.tid, 4);
-  ASSERT_EQ(thread.upid, 1);
+  ASSERT_EQ(thread.upid.value(), 1);
   ASSERT_EQ(process.pid, 2);
   ASSERT_EQ(process.start_ns, timestamp);
 }
@@ -101,7 +101,7 @@
   ASSERT_EQ(context.storage->thread_count(), 1);
   auto tid_it = context.process_tracker->UtidsForTid(12);
   ASSERT_NE(tid_it.first, tid_it.second);
-  ASSERT_EQ(thread.upid, 1);
+  ASSERT_EQ(thread.upid.value(), 1);
   auto pid_it = context.process_tracker->UpidsForPid(2);
   ASSERT_NE(pid_it.first, pid_it.second);
   ASSERT_EQ(context.storage->process_count(), 1);
diff --git a/src/trace_processor/proto_trace_parser.cc b/src/trace_processor/proto_trace_parser.cc
index fc6ad1f..f765a33 100644
--- a/src/trace_processor/proto_trace_parser.cc
+++ b/src/trace_processor/proto_trace_parser.cc
@@ -443,8 +443,8 @@
   }
 
   UniqueTid utid = context_->process_tracker->UpdateThread(ts, pid, 0);
-  UniquePid upid = context_->storage->GetThread(utid).upid;
-  if (upid == 0) {
+  auto opt_upid = context_->storage->GetThread(utid).upid;
+  if (!opt_upid.has_value()) {
     PERFETTO_DLOG("Could not find process associated with utid %" PRIu32
                   " when parsing mem counters.",
                   utid);
@@ -461,7 +461,8 @@
     // pre-cached |proc_mem_counter_names_| map.
     StringId name = proc_mem_counter_names_[field_id];
     uint64_t value = counter_values[field_id];
-    context_->event_tracker->PushCounter(ts, value, name, upid, RefType::kUpid);
+    context_->event_tracker->PushCounter(ts, value, name, opt_upid.value(),
+                                         RefType::kUpid);
   }
 
   PERFETTO_DCHECK(decoder.IsEndOfBuffer());
@@ -666,8 +667,8 @@
     return;
   }
   UniqueTid utid = context_->process_tracker->UpdateThread(timestamp, pid, 0);
-  UniquePid upid = context_->storage->GetThread(utid).upid;
-  if (upid == 0) {
+  auto opt_upid = context_->storage->GetThread(utid).upid;
+  if (!opt_upid.has_value()) {
     PERFETTO_DLOG("Could not find process associated with utid %" PRIu32
                   " when parsing rss stat.",
                   utid);
@@ -676,7 +677,7 @@
   }
 
   context_->event_tracker->PushCounter(timestamp, size, rss_members_[member],
-                                       upid, RefType::kUpid);
+                                       opt_upid.value(), RefType::kUpid);
   PERFETTO_DCHECK(decoder.IsEndOfBuffer());
 }
 
diff --git a/src/trace_processor/thread_table.cc b/src/trace_processor/thread_table.cc
index 52d1137..6e9b97c 100644
--- a/src/trace_processor/thread_table.cc
+++ b/src/trace_processor/thread_table.cc
@@ -70,7 +70,7 @@
                             const QueryConstraints& qc,
                             sqlite3_value** argv)
     : storage_(storage) {
-  min = 1;
+  min = 0;
   max = static_cast<uint32_t>(storage_->thread_count());
   desc = false;
   current = min;
@@ -108,7 +108,7 @@
       break;
     }
     case Column::kUpid: {
-      sqlite3_result_int64(context, thread.upid);
+      sqlite3_result_int64(context, thread.upid.value_or(0));
       break;
     }
     case Column::kName: {
diff --git a/src/trace_processor/trace_storage.h b/src/trace_processor/trace_storage.h
index 621bae7..9100c34 100644
--- a/src/trace_processor/trace_storage.h
+++ b/src/trace_processor/trace_storage.h
@@ -25,6 +25,7 @@
 #include <vector>
 
 #include "perfetto/base/logging.h"
+#include "perfetto/base/optional.h"
 #include "perfetto/base/string_view.h"
 #include "perfetto/base/utils.h"
 
@@ -84,7 +85,7 @@
     uint64_t start_ns = 0;
     uint64_t end_ns = 0;
     StringId name_id = 0;
-    UniquePid upid = 0;
+    base::Optional<UniquePid> upid;
     uint32_t tid = 0;
   };