Trace Redaction - Create integration test pattern

We've narrowed in on a pattern for implementing integration tests. To
make this easier - and to ensure test stability (e.g. handling file
IO) - this creates a simple class that can be inherited alongside
other test classes.

Bug: 318576499
Change-Id: I87051283e3a2975f27a936b1271c0c7bcdcfc3d7
diff --git a/src/trace_redaction/BUILD.gn b/src/trace_redaction/BUILD.gn
index 1f088ea..f908e96 100644
--- a/src/trace_redaction/BUILD.gn
+++ b/src/trace_redaction/BUILD.gn
@@ -84,6 +84,8 @@
     "scrub_ftrace_events_integrationtest.cc",
     "scrub_process_trees_integrationtest.cc",
     "scrub_task_rename_integrationtest.cc",
+    "trace_redaction_integration_fixture.cc",
+    "trace_redaction_integration_fixture.h",
     "trace_redactor_integrationtest.cc",
   ]
   deps = [
diff --git a/src/trace_redaction/filter_sched_waking_events_integrationtest.cc b/src/trace_redaction/filter_sched_waking_events_integrationtest.cc
index d0e959e..08bc991 100644
--- a/src/trace_redaction/filter_sched_waking_events_integrationtest.cc
+++ b/src/trace_redaction/filter_sched_waking_events_integrationtest.cc
@@ -31,6 +31,7 @@
 #include "src/trace_redaction/optimize_timeline.h"
 #include "src/trace_redaction/scrub_ftrace_events.h"
 #include "src/trace_redaction/trace_redaction_framework.h"
+#include "src/trace_redaction/trace_redaction_integration_fixture.h"
 #include "src/trace_redaction/trace_redactor.h"
 #include "test/gtest_and_gmock.h"
 
@@ -43,60 +44,24 @@
 namespace perfetto::trace_redaction {
 namespace {
 
-constexpr std::string_view kTracePath =
-    "test/data/trace-redaction-general.pftrace";
 constexpr std::string_view kPackageName =
     "com.Unity.com.unity.multiplayer.samples.coop";
 
-class RedactSchedWakingIntegrationTest : public testing::Test {
+class RedactSchedWakingIntegrationTest
+    : public testing::Test,
+      protected TraceRedactionIntegrationFixure {
  protected:
   void SetUp() override {
+    trace_redactor()->emplace_collect<FindPackageUid>();
+    trace_redactor()->emplace_collect<BuildTimeline>();
+    trace_redactor()->emplace_build<OptimizeTimeline>();
 
-    redactor_.emplace_collect<FindPackageUid>();
-    redactor_.emplace_collect<BuildTimeline>();
-    redactor_.emplace_build<OptimizeTimeline>();
+    auto* ftrace_filter =
+        trace_redactor()->emplace_transform<ScrubFtraceEvents>();
+    ftrace_filter->emplace_back<FilterSchedWakingEvents>();
 
-    auto transformer = redactor_.emplace_transform<ScrubFtraceEvents>();
-    transformer->emplace_back<FilterSchedWakingEvents>();
-
-    context_.package_name = kPackageName;
-
-    src_trace_ = base::GetTestDataPath(std::string(kTracePath));
-
-    dest_trace_ = tmp_dir_.AbsolutePath("dst.pftrace");
-    tmp_dir_.TrackFile("dst.pftrace");
+    context()->package_name = kPackageName;
   }
-
-  base::Status Redact() {
-    return redactor_.Redact(src_trace_, dest_trace_, &context_);
-  }
-
-  base::StatusOr<std::string> LoadOriginal() const {
-    return ReadRawTrace(src_trace_);
-  }
-
-  base::StatusOr<std::string> LoadRedacted() const {
-    return ReadRawTrace(dest_trace_);
-  }
-
- private:
-  base::StatusOr<std::string> ReadRawTrace(const std::string& path) const {
-    std::string redacted_buffer;
-
-    if (base::ReadFile(path, &redacted_buffer)) {
-      return redacted_buffer;
-    }
-
-    return base::ErrStatus("Failed to read %s", path.c_str());
-  }
-
-  Context context_;
-  TraceRedactor redactor_;
-
-  base::TmpDirTree tmp_dir_;
-
-  std::string src_trace_;
-  std::string dest_trace_;
 };
 
 // >>> SELECT uid
diff --git a/src/trace_redaction/redact_sched_switch_integrationtest.cc b/src/trace_redaction/redact_sched_switch_integrationtest.cc
index 26dd400..9480977 100644
--- a/src/trace_redaction/redact_sched_switch_integrationtest.cc
+++ b/src/trace_redaction/redact_sched_switch_integrationtest.cc
@@ -16,20 +16,16 @@
 
 #include <cstdint>
 #include <string>
-#include <string_view>
-#include <vector>
 
 #include "perfetto/base/status.h"
-#include "perfetto/ext/base/file_utils.h"
 #include "perfetto/ext/base/flat_hash_map.h"
 #include "src/base/test/status_matchers.h"
-#include "src/base/test/tmp_dir_tree.h"
-#include "src/base/test/utils.h"
 #include "src/trace_redaction/build_timeline.h"
 #include "src/trace_redaction/find_package_uid.h"
 #include "src/trace_redaction/optimize_timeline.h"
 #include "src/trace_redaction/redact_sched_switch.h"
 #include "src/trace_redaction/trace_redaction_framework.h"
+#include "src/trace_redaction/trace_redaction_integration_fixture.h"
 #include "src/trace_redaction/trace_redactor.h"
 #include "test/gtest_and_gmock.h"
 
@@ -40,59 +36,19 @@
 #include "protos/perfetto/trace/trace_packet.pbzero.h"
 
 namespace perfetto::trace_redaction {
-namespace {
 
-constexpr std::string_view kTracePath =
-    "test/data/trace-redaction-general.pftrace";
-constexpr std::string_view kPackageName =
-    "com.Unity.com.unity.multiplayer.samples.coop";
-
-class RedactSchedSwitchIntegrationTest : public testing::Test {
+class RedactSchedSwitchIntegrationTest
+    : public testing::Test,
+      protected TraceRedactionIntegrationFixure {
  protected:
   void SetUp() override {
-    redactor_.emplace_collect<FindPackageUid>();
-    redactor_.emplace_collect<BuildTimeline>();
-    redactor_.emplace_build<OptimizeTimeline>();
-    redactor_.emplace_transform<RedactSchedSwitch>();
+    trace_redactor()->emplace_collect<FindPackageUid>();
+    trace_redactor()->emplace_collect<BuildTimeline>();
+    trace_redactor()->emplace_build<OptimizeTimeline>();
+    trace_redactor()->emplace_transform<RedactSchedSwitch>();
 
-    context_.package_name = kPackageName;
-
-    src_trace_ = base::GetTestDataPath(std::string(kTracePath));
-
-    dest_trace_ = tmp_dir_.AbsolutePath("dst.pftrace");
-    tmp_dir_.TrackFile("dst.pftrace");
+    context()->package_name = "com.Unity.com.unity.multiplayer.samples.coop";
   }
-
-  base::Status Redact() {
-    return redactor_.Redact(src_trace_, dest_trace_, &context_);
-  }
-
-  base::StatusOr<std::string> LoadOriginal() const {
-    return ReadRawTrace(src_trace_);
-  }
-
-  base::StatusOr<std::string> LoadRedacted() const {
-    return ReadRawTrace(dest_trace_);
-  }
-
- private:
-  base::StatusOr<std::string> ReadRawTrace(const std::string& path) const {
-    std::string redacted_buffer;
-
-    if (base::ReadFile(path, &redacted_buffer)) {
-      return redacted_buffer;
-    }
-
-    return base::ErrStatus("Failed to read %s", path.c_str());
-  }
-
-  Context context_;
-  TraceRedactor redactor_;
-
-  base::TmpDirTree tmp_dir_;
-
-  std::string src_trace_;
-  std::string dest_trace_;
 };
 
 // >>> SELECT uid
@@ -233,5 +189,4 @@
   }
 }
 
-}  // namespace
 }  // namespace perfetto::trace_redaction
diff --git a/src/trace_redaction/scrub_process_trees_integrationtest.cc b/src/trace_redaction/scrub_process_trees_integrationtest.cc
index 61a7bcd..7d13721 100644
--- a/src/trace_redaction/scrub_process_trees_integrationtest.cc
+++ b/src/trace_redaction/scrub_process_trees_integrationtest.cc
@@ -30,6 +30,7 @@
 #include "src/trace_redaction/optimize_timeline.h"
 #include "src/trace_redaction/scrub_process_trees.h"
 #include "src/trace_redaction/trace_redaction_framework.h"
+#include "src/trace_redaction/trace_redaction_integration_fixture.h"
 #include "src/trace_redaction/trace_redactor.h"
 #include "test/gtest_and_gmock.h"
 
@@ -37,14 +38,14 @@
 
 namespace {
 
-constexpr std::string_view kTracePath =
-    "test/data/trace-redaction-general.pftrace";
 constexpr std::string_view kProcessName =
     "com.Unity.com.unity.multiplayer.samples.coop";
 
 }  // namespace
 
-class ScrubProcessTreesIntegrationTest : public testing::Test {
+class ScrubProcessTreesIntegrationTest
+    : public testing::Test,
+      protected TraceRedactionIntegrationFixure {
  protected:
   void SetUp() override {
     // ScrubProcessTrees depends on:
@@ -58,30 +59,13 @@
     // BuildTimeline depends on.... nothing
     // FindPackageUid depends on... nothing
 
-    redactor_.emplace_collect<FindPackageUid>();
-    redactor_.emplace_collect<BuildTimeline>();
-    redactor_.emplace_build<OptimizeTimeline>();
-    redactor_.emplace_transform<ScrubProcessTrees>();
+    trace_redactor()->emplace_collect<FindPackageUid>();
+    trace_redactor()->emplace_collect<BuildTimeline>();
+    trace_redactor()->emplace_build<OptimizeTimeline>();
+    trace_redactor()->emplace_transform<ScrubProcessTrees>();
 
     // In this case, the process and package have the same name.
-    context_.package_name = kProcessName;
-
-    src_trace_ = base::GetTestDataPath(std::string(kTracePath));
-
-    dest_trace_ = tmp_dir_.AbsolutePath("dst.pftrace");
-    tmp_dir_.TrackFile("dst.pftrace");
-  }
-
-  base::Status Redact() {
-    return redactor_.Redact(src_trace_, dest_trace_, &context_);
-  }
-
-  base::StatusOr<std::string> LoadOriginal() const {
-    return ReadRawTrace(src_trace_);
-  }
-
-  base::StatusOr<std::string> LoadRedacted() const {
-    return ReadRawTrace(dest_trace_);
+    context()->package_name = kProcessName;
   }
 
   std::vector<std::string> CollectProcessNames(
@@ -109,25 +93,6 @@
 
     return names;
   }
-
- private:
-  base::StatusOr<std::string> ReadRawTrace(const std::string& path) const {
-    std::string redacted_buffer;
-
-    if (base::ReadFile(path, &redacted_buffer)) {
-      return redacted_buffer;
-    }
-
-    return base::ErrStatus("Failed to read %s", path.c_str());
-  }
-
-  Context context_;
-  TraceRedactor redactor_;
-
-  base::TmpDirTree tmp_dir_;
-
-  std::string src_trace_;
-  std::string dest_trace_;
 };
 
 TEST_F(ScrubProcessTreesIntegrationTest, RemovesProcessNamesFromProcessTrees) {
diff --git a/src/trace_redaction/scrub_task_rename_integrationtest.cc b/src/trace_redaction/scrub_task_rename_integrationtest.cc
index dee77e6..82903c0 100644
--- a/src/trace_redaction/scrub_task_rename_integrationtest.cc
+++ b/src/trace_redaction/scrub_task_rename_integrationtest.cc
@@ -29,6 +29,7 @@
 #include "src/trace_redaction/optimize_timeline.h"
 #include "src/trace_redaction/scrub_task_rename.h"
 #include "src/trace_redaction/trace_redaction_framework.h"
+#include "src/trace_redaction/trace_redaction_integration_fixture.h"
 #include "src/trace_redaction/trace_redactor.h"
 #include "test/gtest_and_gmock.h"
 
@@ -40,44 +41,29 @@
 namespace perfetto::trace_redaction {
 
 namespace {
-using FtraceEvent = protos::pbzero::FtraceEvent;
 
-constexpr std::string_view kTracePath =
-    "test/data/trace-redaction-general.pftrace";
+using FtraceEvent = protos::pbzero::FtraceEvent;
 
 // Set the package name to "just some package name". If a specific package name
 // is needed, the test it should overwrite this value.
 constexpr std::string_view kPackageName =
     "com.Unity.com.unity.multiplayer.samples.coop";
 
-class RenameEventsTraceRedactorIntegrationTest : public testing::Test {
+}  // namespace
+
+class RenameEventsTraceRedactorIntegrationTest
+    : public testing::Test,
+      protected TraceRedactionIntegrationFixure {
  protected:
   void SetUp() override {
     // In order for ScrubTaskRename to work, it needs the timeline. All
     // registered primitives are there to generate the timeline.
-    redactor_.emplace_collect<FindPackageUid>();
-    redactor_.emplace_collect<BuildTimeline>();
-    redactor_.emplace_build<OptimizeTimeline>();
-    redactor_.emplace_transform<ScrubTaskRename>();
+    trace_redactor()->emplace_collect<FindPackageUid>();
+    trace_redactor()->emplace_collect<BuildTimeline>();
+    trace_redactor()->emplace_build<OptimizeTimeline>();
+    trace_redactor()->emplace_transform<ScrubTaskRename>();
 
-    context_.package_name = kPackageName;
-
-    src_trace_ = base::GetTestDataPath(std::string(kTracePath));
-
-    dest_trace_ = tmp_dir_.AbsolutePath("dst.pftrace");
-    tmp_dir_.TrackFile("dst.pftrace");
-  }
-
-  base::Status Redact() {
-    return redactor_.Redact(src_trace_, dest_trace_, &context_);
-  }
-
-  base::StatusOr<std::string> LoadOriginal() const {
-    return ReadRawTrace(src_trace_);
-  }
-
-  base::StatusOr<std::string> LoadRedacted() const {
-    return ReadRawTrace(dest_trace_);
+    context()->package_name = kPackageName;
   }
 
   std::vector<uint32_t> GetAllRenamedPids(
@@ -105,25 +91,6 @@
 
     return renamed_pids;
   }
-
- private:
-  base::StatusOr<std::string> ReadRawTrace(const std::string& path) const {
-    std::string redacted_buffer;
-
-    if (base::ReadFile(path, &redacted_buffer)) {
-      return redacted_buffer;
-    }
-
-    return base::ErrStatus("Failed to read %s", path.c_str());
-  }
-
-  Context context_;
-  TraceRedactor redactor_;
-
-  base::TmpDirTree tmp_dir_;
-
-  std::string src_trace_;
-  std::string dest_trace_;
 };
 
 TEST_F(RenameEventsTraceRedactorIntegrationTest, RemovesUnwantedRenameTasks) {
@@ -153,5 +120,4 @@
   ASSERT_TRUE(redacted_rename_pids.empty());
 }
 
-}  // namespace
 }  // namespace perfetto::trace_redaction
diff --git a/src/trace_redaction/trace_redaction_integration_fixture.cc b/src/trace_redaction/trace_redaction_integration_fixture.cc
new file mode 100644
index 0000000..85555f3
--- /dev/null
+++ b/src/trace_redaction/trace_redaction_integration_fixture.cc
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * 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 "src/trace_redaction/trace_redaction_integration_fixture.h"
+
+#include "perfetto/ext/base/file_utils.h"
+#include "src/base/test/utils.h"
+
+namespace perfetto::trace_redaction {
+
+TraceRedactionIntegrationFixure::TraceRedactionIntegrationFixure() {
+  src_trace_ =
+      base::GetTestDataPath("test/data/trace-redaction-general.pftrace");
+  dest_trace_ = tmp_dir_.AbsolutePath("dst.pftrace");
+}
+
+base::Status TraceRedactionIntegrationFixure::Redact() {
+  auto status = trace_redactor_.Redact(src_trace_, dest_trace_, &context_);
+
+  if (status.ok()) {
+    tmp_dir_.TrackFile("dst.pftrace");
+  }
+
+  return status;
+}
+
+base::StatusOr<std::string> TraceRedactionIntegrationFixure::LoadOriginal()
+    const {
+  return ReadRawTrace(src_trace_);
+}
+
+base::StatusOr<std::string> TraceRedactionIntegrationFixure::LoadRedacted()
+    const {
+  return ReadRawTrace(dest_trace_);
+}
+
+base::StatusOr<std::string> TraceRedactionIntegrationFixure::ReadRawTrace(
+    const std::string& path) const {
+  std::string redacted_buffer;
+
+  if (base::ReadFile(path, &redacted_buffer)) {
+    return redacted_buffer;
+  }
+
+  return base::ErrStatus("Failed to read %s", path.c_str());
+}
+
+}  // namespace perfetto::trace_redaction
diff --git a/src/trace_redaction/trace_redaction_integration_fixture.h b/src/trace_redaction/trace_redaction_integration_fixture.h
new file mode 100644
index 0000000..55060f9
--- /dev/null
+++ b/src/trace_redaction/trace_redaction_integration_fixture.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef SRC_TRACE_REDACTION_TRACE_REDACTION_INTEGRATION_FIXTURE_H_
+#define SRC_TRACE_REDACTION_TRACE_REDACTION_INTEGRATION_FIXTURE_H_
+
+#include <string>
+
+#include "perfetto/ext/base/status_or.h"
+#include "src/base/test/tmp_dir_tree.h"
+#include "src/trace_redaction/trace_redaction_framework.h"
+#include "src/trace_redaction/trace_redactor.h"
+
+namespace perfetto::trace_redaction {
+
+class TraceRedactionIntegrationFixure {
+ protected:
+  TraceRedactionIntegrationFixure();
+
+  // Redact the source file and write it to the destination file. The contents
+  // of each file can be read using LoadOriginal() and LoadRedacted().
+  base::Status Redact();
+
+  base::StatusOr<std::string> LoadOriginal() const;
+
+  base::StatusOr<std::string> LoadRedacted() const;
+
+  Context* context() { return &context_; }
+
+  TraceRedactor* trace_redactor() { return &trace_redactor_; }
+
+ private:
+  base::StatusOr<std::string> ReadRawTrace(const std::string& path) const;
+
+  Context context_;
+
+  TraceRedactor trace_redactor_;
+
+  base::TmpDirTree tmp_dir_;
+
+  std::string src_trace_;
+
+  // Path to the redacted trace. This will only be valid after Redact()
+  // completely. If redaction was successful, this file will be tracked by
+  // tmp_dir_.
+  std::string dest_trace_;
+};
+
+}  // namespace perfetto::trace_redaction
+
+#endif  // SRC_TRACE_REDACTION_TRACE_REDACTION_INTEGRATION_FIXTURE_H_