summaryrefslogtreecommitdiffstats
path: root/third_party/rust/rkv/tests/test_txn.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:47:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:47:29 +0000
commit0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d (patch)
treea31f07c9bcca9d56ce61e9a1ffd30ef350d513aa /third_party/rust/rkv/tests/test_txn.rs
parentInitial commit. (diff)
downloadfirefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.tar.xz
firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.zip
Adding upstream version 115.8.0esr.upstream/115.8.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/rkv/tests/test_txn.rs')
-rw-r--r--third_party/rust/rkv/tests/test_txn.rs131
1 files changed, 131 insertions, 0 deletions
diff --git a/third_party/rust/rkv/tests/test_txn.rs b/third_party/rust/rkv/tests/test_txn.rs
new file mode 100644
index 0000000000..1e8fdfb416
--- /dev/null
+++ b/third_party/rust/rkv/tests/test_txn.rs
@@ -0,0 +1,131 @@
+// Copyright 2018-2019 Mozilla
+//
+// 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.
+#![cfg(feature = "db-dup-sort")]
+
+use std::fs;
+
+use tempfile::Builder;
+
+use rkv::{
+ backend::{SafeMode, SafeModeDatabase, SafeModeRoCursor, SafeModeRwTransaction},
+ Readable, Rkv, StoreOptions, Value, Writer,
+};
+
+/// Consider a struct like this:
+/// struct Sample {
+/// id: u64,
+/// value: String,
+/// date: String,
+/// }
+/// We would like to index all of the fields so that we can search for the struct not only
+/// by ID but also by value and date. When we index the fields individually in their own
+/// tables, it is important that we run all operations within a single transaction to
+/// ensure coherence of the indices.
+/// This test features helper functions for reading and writing the parts of the struct.
+/// Note that the reader functions take `Readable` because they might run within a Read
+/// Transaction or a Write Transaction. The test demonstrates fetching values via both.
+
+type SingleStore = rkv::SingleStore<SafeModeDatabase>;
+type MultiStore = rkv::MultiStore<SafeModeDatabase>;
+
+#[test]
+fn read_many() {
+ let root = Builder::new()
+ .prefix("test_txns")
+ .tempdir()
+ .expect("tempdir");
+ fs::create_dir_all(root.path()).expect("dir created");
+ let k = Rkv::new::<SafeMode>(root.path()).expect("new succeeded");
+ let samplestore = k.open_single("s", StoreOptions::create()).expect("open");
+ let datestore = k.open_multi("m", StoreOptions::create()).expect("open");
+ let valuestore = k.open_multi("m", StoreOptions::create()).expect("open");
+
+ {
+ let mut writer = k.write().expect("env write lock");
+
+ for id in 0..30_u64 {
+ let value = format!("value{id}");
+ let date = format!("2019-06-{id}");
+ put_id_field(&mut writer, datestore, &date, id);
+ put_id_field(&mut writer, valuestore, &value, id);
+ put_sample(&mut writer, samplestore, id, &value);
+ }
+
+ // now we read in the same transaction
+ for id in 0..30_u64 {
+ let value = format!("value{id}");
+ let date = format!("2019-06-{id}");
+ let ids = get_ids_by_field(&writer, datestore, &date);
+ let ids2 = get_ids_by_field(&writer, valuestore, &value);
+ let samples = get_samples(&writer, samplestore, &ids);
+ let samples2 = get_samples(&writer, samplestore, &ids2);
+ println!("{samples:?}, {samples2:?}");
+ }
+ }
+
+ {
+ let reader = k.read().expect("env read lock");
+ for id in 0..30_u64 {
+ let value = format!("value{id}");
+ let date = format!("2019-06-{id}");
+ let ids = get_ids_by_field(&reader, datestore, &date);
+ let ids2 = get_ids_by_field(&reader, valuestore, &value);
+ let samples = get_samples(&reader, samplestore, &ids);
+ let samples2 = get_samples(&reader, samplestore, &ids2);
+ println!("{samples:?}, {samples2:?}");
+ }
+ }
+}
+
+fn get_ids_by_field<'t, T>(txn: &'t T, store: MultiStore, field: &'t str) -> Vec<u64>
+where
+ T: Readable<'t, Database = SafeModeDatabase, RoCursor = SafeModeRoCursor<'t>>,
+{
+ store
+ .get(txn, field)
+ .expect("get iterator")
+ .map(|id| match id.expect("field") {
+ (_, Value::U64(id)) => id,
+ _ => panic!("getting value in iter"),
+ })
+ .collect::<Vec<u64>>()
+}
+
+fn get_samples<'t, T>(txn: &'t T, samplestore: SingleStore, ids: &[u64]) -> Vec<String>
+where
+ T: Readable<'t, Database = SafeModeDatabase, RoCursor = SafeModeRoCursor<'t>>,
+{
+ ids.iter()
+ .map(|id| {
+ let bytes = id.to_be_bytes();
+ match samplestore.get(txn, &bytes).expect("fetch sample") {
+ Some(Value::Str(sample)) => String::from(sample),
+ Some(_) => panic!("wrong type"),
+ None => panic!("no sample for this id!"),
+ }
+ })
+ .collect::<Vec<String>>()
+}
+
+fn put_sample(
+ txn: &mut Writer<SafeModeRwTransaction>,
+ samplestore: SingleStore,
+ id: u64,
+ value: &str,
+) {
+ let idbytes = id.to_be_bytes();
+ samplestore
+ .put(txn, &idbytes, &Value::Str(value))
+ .expect("put id");
+}
+
+fn put_id_field(txn: &mut Writer<SafeModeRwTransaction>, store: MultiStore, field: &str, id: u64) {
+ store.put(txn, field, &Value::U64(id)).expect("put id");
+}