[archivist] Fix tests for CTF

This test has been mysteriously failing in CTF but passing at HEAD for
the last few API rolls, and we now know why.

At API level HEAD we default the format for Inspect reads to CBOR which
is more efficient, but not yet formally stabilized. At levels < HEAD,
however, we default to JSON which is less space efficient.

The truncation test sets the maximum byte size to 4000 bytes, which
gives 1333 bytes for each of the 3 components that are being read. This
happens to fit the CBOR content, but not the JSON content. Whenever we
roll a new API level we create a version of this test that requests the
JSON content which becomes fully truncated (similar to the case where we
set the maximum size to 1 byte).

This change creates a new method on the ArchiveReader to set the read
format. If that method is not called we revert to the default FORMAT as
before. The test now includes a new read that checks that whatever
number we pick can fit a JSON response too, and we set the maximum
aggregated size to 8000 instead of 4000 since that is enough to fit
either JSON or CBOR.

Fixed: 383560524
Change-Id: Ibe75ce0532f0c4dc161d1c2ae0a723d416ef4b29
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/1609931
Reviewed-by: Brian Bosak <bbosak@google.com>
diff --git a/src/diagnostics/archivist/tests/integration/realm_factory/meta/realm_factory.cml b/src/diagnostics/archivist/tests/integration/realm_factory/meta/realm_factory.cml
index a59317c..e34d995 100644
--- a/src/diagnostics/archivist/tests/integration/realm_factory/meta/realm_factory.cml
+++ b/src/diagnostics/archivist/tests/integration/realm_factory/meta/realm_factory.cml
@@ -21,7 +21,7 @@
             to: "#realm_builder",
         },
 
-        // Offers required for realm_builder to run archvist.
+        // Offers required for realm_builder to run archivist.
         //
         // LINT.IfChange
         {
diff --git a/src/diagnostics/archivist/tests/integration/test_cases/src/inspect/truncation.rs b/src/diagnostics/archivist/tests/integration/test_cases/src/inspect/truncation.rs
index 43cdc1e..a3c4c5a 100644
--- a/src/diagnostics/archivist/tests/integration/test_cases/src/inspect/truncation.rs
+++ b/src/diagnostics/archivist/tests/integration/test_cases/src/inspect/truncation.rs
@@ -49,8 +49,28 @@
 
     assert_eq!(count_dropped_schemas_per_moniker(&data, "child_a"), 3);
 
+    const MAX_EXPECTED_BYTES_FOR_3_COMPONENTS: u64 = 8000;
+
+    // Use the default format with this read. At HEAD this will be CBOR, but when frozen for CTF
+    // we will fall back to JSON.
+    //
+    // Leave enough room for the result of 3 components in this read and the following one.
     let data = reader
-        .with_aggregated_result_bytes_limit(4000)
+        .with_aggregated_result_bytes_limit(MAX_EXPECTED_BYTES_FOR_3_COMPONENTS)
+        .add_selector("child_a*:root")
+        .with_minimum_schema_count(3)
+        .snapshot()
+        .await
+        .expect("got inspect data");
+
+    assert_eq!(data.len(), 3);
+
+    assert_eq!(count_dropped_schemas_per_moniker(&data, "child_a"), 0);
+
+    // Force use of JSON for this read, ensuring that we still fit within the limit.
+    let data = reader
+        .with_format(fidl_fuchsia_diagnostics::Format::Json)
+        .with_aggregated_result_bytes_limit(MAX_EXPECTED_BYTES_FOR_3_COMPONENTS)
         .add_selector("child_a*:root")
         .with_minimum_schema_count(3)
         .snapshot()
@@ -74,8 +94,23 @@
     assert_eq!(count_dropped_schemas_per_moniker(&data, "child_a"), 3);
     assert_eq!(count_dropped_schemas_per_moniker(&data, "child_b"), 3);
 
+    // Similar to the above reads, ensure that we leave enough room for 6 components' output.
     let data = reader
-        .with_aggregated_result_bytes_limit(8000)
+        .with_aggregated_result_bytes_limit(2 * MAX_EXPECTED_BYTES_FOR_3_COMPONENTS)
+        .add_selector("child_b*:root")
+        .add_selector("child_a*:root")
+        .with_minimum_schema_count(6)
+        .snapshot()
+        .await
+        .expect("got inspect data");
+
+    assert_eq!(data.len(), 6);
+    assert_eq!(count_dropped_schemas_per_moniker(&data, "child_a"), 0);
+    assert_eq!(count_dropped_schemas_per_moniker(&data, "child_b"), 0);
+
+    let data = reader
+        .with_format(fidl_fuchsia_diagnostics::Format::Json)
+        .with_aggregated_result_bytes_limit(2 * MAX_EXPECTED_BYTES_FOR_3_COMPONENTS)
         .add_selector("child_b*:root")
         .add_selector("child_a*:root")
         .with_minimum_schema_count(6)
diff --git a/src/lib/diagnostics/reader/rust/src/lib.rs b/src/lib/diagnostics/reader/rust/src/lib.rs
index 0013f12..1a503cd 100644
--- a/src/lib/diagnostics/reader/rust/src/lib.rs
+++ b/src/lib/diagnostics/reader/rust/src/lib.rs
@@ -346,11 +346,11 @@
     }
 
     /// Connects to the ArchiveAccessor and returns data matching provided selectors.
-    async fn snapshot_shared<D>(&self) -> Result<Vec<Data<D>>, Error>
+    async fn snapshot_shared<D>(&self, format: Format) -> Result<Vec<Data<D>>, Error>
     where
         D: DiagnosticsData + 'static,
     {
-        let data_future = self.snapshot_inner::<D, Data<D>>(FORMAT);
+        let data_future = self.snapshot_inner::<D, Data<D>>(format);
         let data = match self.timeout {
             Some(timeout) => data_future.on_timeout(timeout.after_now(), || Ok(Vec::new())).await?,
             None => data_future.await?,
@@ -553,9 +553,23 @@
         self
     }
 
+    /// Sets the format to use when reading inspect data.
+    pub fn with_format(&mut self, format: Format) -> &mut Self {
+        self.format = Some(format);
+        self
+    }
+
+    #[inline]
+    fn format(&self) -> Format {
+        match self.format {
+            Some(f) => f,
+            None => FORMAT,
+        }
+    }
+
     /// Connects to the ArchiveAccessor and returns data matching provided selectors.
     pub async fn snapshot(&self) -> Result<Vec<Data<Inspect>>, Error> {
-        self.snapshot_shared::<Inspect>().await
+        self.snapshot_shared::<Inspect>(self.format()).await
     }
 }