Skip to content

Commit af65419

Browse files
authored
Listing scopes will not include the global scope. (#1307)
This PR changes the function that collects all scopes for a given store to not include the global scope. This restores the behaviour of kvx. As a side effect, it changes the store testing code to run on both backends.
1 parent c22f766 commit af65419

File tree

7 files changed

+384
-279
lines changed

7 files changed

+384
-279
lines changed

src/commons/storage/backends/disk.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -343,8 +343,12 @@ impl Store {
343343
}
344344
};
345345
match self.path_scope(path) {
346-
Some(scope) => res.push(scope),
347-
None => return Ok(())
346+
Some(scope) => {
347+
if !scope.is_global() {
348+
res.push(scope)
349+
}
350+
}
351+
_ => return Ok(())
348352
};
349353
for item in dir {
350354
let item = match item {

src/commons/storage/backends/memory.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ pub struct Store {
2727
}
2828

2929
impl Store {
30+
pub fn wipe_all() {
31+
MEMORY.wipe_all()
32+
}
33+
3034
pub fn from_uri(
3135
uri: &Url, namespace: &Namespace
3236
) -> Result<Option<Self>, Error> {
@@ -133,7 +137,11 @@ impl Store {
133137
/// Returns all the scopes in the score.
134138
///
135139
pub fn list_scopes(&self) -> Result<Vec<Scope>, Error> {
136-
Ok(self.namespace.values().keys().cloned().collect())
140+
Ok(
141+
self.namespace.values().keys().filter(|scope| {
142+
!scope.is_global()
143+
}).cloned().collect()
144+
)
137145
}
138146
}
139147

@@ -301,6 +309,10 @@ struct Memory {
301309
}
302310

303311
impl Memory {
312+
fn wipe_all(&self) {
313+
self.namespaces.lock().expect("poisoned lock").clear();
314+
}
315+
304316
fn get_namespace(
305317
&self,
306318
prefix: String,

src/commons/storage/backends/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// file.
88

99
mod disk;
10-
mod memory;
10+
pub(super) mod memory; // Test code wants to access the Store directly.
1111

1212

1313
//============ Backend Enum ==================================================

src/commons/storage/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ pub use self::types::{
1010
mod backends;
1111
mod store;
1212
mod types;
13+
mod test;
1314

src/commons/storage/store.rs

Lines changed: 7 additions & 274 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,9 @@ impl KeyValueStore {
117117
self.execute(key.scope(), |kv| kv.has(key))
118118
}
119119

120-
/// Delete a key-value pair
120+
/// Delete a key-value pair.
121+
///
122+
/// Returns an error if the key does not exist.
121123
pub fn drop_key(&self, key: &Key) -> Result<(), KeyValueError> {
122124
self.execute(key.scope(), |kv| kv.delete(key))
123125
}
@@ -159,7 +161,10 @@ impl KeyValueStore {
159161
self.execute(scope, |kv| kv.delete_scope(scope))
160162
}
161163

162-
/// Returns all scopes, including sub_scopes
164+
/// Returns all scopes.
165+
///
166+
/// The returned vec will contain all scopes, including their subscopes.
167+
/// It will not, however, contain the global scope.
163168
pub fn scopes(&self) -> Result<Vec<Scope>, KeyValueError> {
164169
self.execute(&Scope::global(), |kv| kv.list_scopes())
165170
}
@@ -294,275 +299,3 @@ impl fmt::Display for KeyValueError {
294299
}
295300
}
296301

297-
//------------ Tests ---------------------------------------------------------
298-
299-
#[cfg(test)]
300-
mod tests {
301-
use std::env;
302-
use rand::{distr::Alphanumeric, Rng};
303-
use crate::commons::storage::{Segment, SegmentBuf};
304-
use super::*;
305-
306-
fn random_segment() -> SegmentBuf {
307-
rand::rng()
308-
.sample_iter(&Alphanumeric)
309-
.take(8)
310-
.map(char::from)
311-
.collect::<String>()
312-
.parse()
313-
.unwrap()
314-
}
315-
316-
fn random_namespace() -> NamespaceBuf {
317-
rand::rng()
318-
.sample_iter(&Alphanumeric)
319-
.take(8)
320-
.map(char::from)
321-
.collect::<String>()
322-
.parse()
323-
.unwrap()
324-
}
325-
326-
fn get_storage_uri() -> Url {
327-
env::var("KRILL_KV_STORAGE_URL")
328-
.ok()
329-
.and_then(|s| Url::parse(&s).ok())
330-
.unwrap_or_else(|| Url::parse("memory:///tmp").unwrap())
331-
}
332-
333-
#[test]
334-
fn test_store() {
335-
let storage_uri = get_storage_uri();
336-
337-
let store =
338-
KeyValueStore::create(&storage_uri, &random_namespace()).unwrap();
339-
let content = "content".to_owned();
340-
let key = Key::new_global(random_segment());
341-
342-
store.store(&key, &content).unwrap();
343-
assert!(store.has(&key).unwrap());
344-
assert_eq!(store.get(&key).unwrap(), Some(content));
345-
}
346-
347-
#[test]
348-
fn test_store_new() {
349-
let storage_uri = get_storage_uri();
350-
351-
let store =
352-
KeyValueStore::create(&storage_uri, &random_namespace()).unwrap();
353-
let content = "content".to_owned();
354-
let key = Key::new_global(random_segment());
355-
356-
assert!(store.store_new(&key, &content).is_ok());
357-
assert!(store.store_new(&key, &content).is_err());
358-
}
359-
360-
#[test]
361-
fn test_store_scoped() {
362-
let storage_uri = get_storage_uri();
363-
364-
let store =
365-
KeyValueStore::create(&storage_uri, &random_namespace()).unwrap();
366-
let content = "content".to_owned();
367-
let id = random_segment();
368-
let scope = Scope::from_segment(Segment::make("scope"));
369-
let key = Key::new_scoped(scope.clone(), id.clone());
370-
371-
store.store(&key, &content).unwrap();
372-
assert!(store.has(&key).unwrap());
373-
assert_eq!(store.get(&key).unwrap(), Some(content.clone()));
374-
assert!(store.has_scope(&scope).unwrap());
375-
376-
let simple = Key::new_global(id);
377-
store.store(&simple, &content).unwrap();
378-
assert!(store.has(&simple).unwrap());
379-
assert_eq!(store.get(&simple).unwrap(), Some(content));
380-
}
381-
382-
#[test]
383-
fn test_get() {
384-
let storage_uri = get_storage_uri();
385-
386-
let store =
387-
KeyValueStore::create(&storage_uri, &random_namespace()).unwrap();
388-
let content = "content".to_owned();
389-
let key = Key::new_global(random_segment());
390-
assert_eq!(store.get::<String>(&key).unwrap(), None);
391-
392-
store.store(&key, &content).unwrap();
393-
assert_eq!(store.get(&key).unwrap(), Some(content));
394-
}
395-
396-
#[test]
397-
fn test_get_transactional() {
398-
let storage_uri = get_storage_uri();
399-
400-
let store =
401-
KeyValueStore::create(&storage_uri, &random_namespace()).unwrap();
402-
let content = "content".to_owned();
403-
let key = Key::new_global(random_segment());
404-
assert_eq!(store.get::<String>(&key).unwrap(), None);
405-
406-
store.store(&key, &content).unwrap();
407-
assert_eq!(store.get(&key).unwrap(), Some(content));
408-
}
409-
410-
#[test]
411-
fn test_has() {
412-
let storage_uri = get_storage_uri();
413-
414-
let store =
415-
KeyValueStore::create(&storage_uri, &random_namespace()).unwrap();
416-
let content = "content".to_owned();
417-
let key = Key::new_global(random_segment());
418-
assert!(!store.has(&key).unwrap());
419-
420-
store.store(&key, &content).unwrap();
421-
assert!(store.has(&key).unwrap());
422-
}
423-
424-
#[test]
425-
fn test_drop_key() {
426-
let storage_uri = get_storage_uri();
427-
428-
let store =
429-
KeyValueStore::create(&storage_uri, &random_namespace()).unwrap();
430-
let content = "content".to_owned();
431-
let key = Key::new_global(random_segment());
432-
store.store(&key, &content).unwrap();
433-
assert!(store.has(&key).unwrap());
434-
435-
store.drop_key(&key).unwrap();
436-
assert!(!store.has(&key).unwrap());
437-
}
438-
439-
#[test]
440-
fn test_drop_scope() {
441-
let storage_uri = get_storage_uri();
442-
443-
let store =
444-
KeyValueStore::create(&storage_uri, &random_namespace()).unwrap();
445-
let content = "content".to_owned();
446-
let scope = Scope::from_segment(random_segment());
447-
let key = Key::new_scoped(scope.clone(), random_segment());
448-
let key2 = Key::new_scoped(
449-
Scope::from_segment(random_segment()),
450-
random_segment(),
451-
);
452-
store.store(&key, &content).unwrap();
453-
store.store(&key2, &content).unwrap();
454-
assert!(store.has_scope(&scope).unwrap());
455-
assert!(store.has(&key).unwrap());
456-
assert!(store.has(&key2).unwrap());
457-
458-
store.drop_scope(&scope).unwrap();
459-
assert!(!store.has_scope(&scope).unwrap());
460-
assert!(!store.has(&key).unwrap());
461-
assert!(store.has(&key2).unwrap());
462-
}
463-
464-
#[test]
465-
fn test_wipe() {
466-
let storage_uri = get_storage_uri();
467-
468-
let store =
469-
KeyValueStore::create(&storage_uri, &random_namespace()).unwrap();
470-
let content = "content".to_owned();
471-
let scope = Scope::from_segment(Segment::make("scope"));
472-
let key = Key::new_scoped(scope.clone(), random_segment());
473-
store.store(&key, &content).unwrap();
474-
assert!(store.has_scope(&scope).unwrap());
475-
assert!(store.has(&key).unwrap());
476-
477-
store.wipe().unwrap();
478-
assert!(!store.has_scope(&scope).unwrap());
479-
assert!(!store.has(&key).unwrap());
480-
assert!(store.keys(&Scope::global(), "").unwrap().is_empty());
481-
}
482-
483-
#[test]
484-
fn test_scopes() {
485-
let storage_uri = get_storage_uri();
486-
487-
let store =
488-
KeyValueStore::create(&storage_uri, &random_namespace()).unwrap();
489-
let content = "content".to_owned();
490-
let id = Segment::make("id");
491-
let scope = Scope::from_segment(random_segment());
492-
let key = Key::new_scoped(scope.clone(), id);
493-
494-
assert!(store.scopes().unwrap().is_empty());
495-
496-
store.store(&key, &content).unwrap();
497-
assert_eq!(store.scopes().unwrap(), [scope.clone()]);
498-
499-
let scope2 = Scope::from_segment(random_segment());
500-
let key2 = Key::new_scoped(scope2.clone(), id);
501-
store.store(&key2, &content).unwrap();
502-
503-
let mut scopes = store.scopes().unwrap();
504-
scopes.sort();
505-
let mut expected = vec![scope.clone(), scope2.clone()];
506-
expected.sort();
507-
assert_eq!(scopes, expected);
508-
509-
store.drop_scope(&scope2).unwrap();
510-
assert_eq!(store.scopes().unwrap(), vec![scope]);
511-
}
512-
513-
#[test]
514-
fn test_has_scope() {
515-
let storage_uri = get_storage_uri();
516-
517-
let store =
518-
KeyValueStore::create(&storage_uri, &random_namespace()).unwrap();
519-
let content = "content".to_owned();
520-
let scope = Scope::from_segment(random_segment());
521-
let key = Key::new_scoped(scope.clone(), Segment::make("id"));
522-
assert!(!store.has_scope(&scope).unwrap());
523-
524-
store.store(&key, &content).unwrap();
525-
assert!(store.has_scope(&scope).unwrap());
526-
}
527-
528-
#[test]
529-
fn test_keys() {
530-
let storage_uri = get_storage_uri();
531-
532-
let store =
533-
KeyValueStore::create(&storage_uri, &random_namespace()).unwrap();
534-
let content = "content".to_owned();
535-
let id = Segment::make("command--id");
536-
let scope = Scope::from_segment(Segment::make("command"));
537-
let key = Key::new_scoped(scope.clone(), id);
538-
539-
let id2 = Segment::make("command--ls");
540-
let id3 = random_segment();
541-
let key2 = Key::new_scoped(scope.clone(), id2);
542-
let key3 = Key::new_global(id3.clone());
543-
544-
store.store(&key, &content).unwrap();
545-
store.store(&key2, &content).unwrap();
546-
store.store(&key3, &content).unwrap();
547-
548-
let mut keys = store.keys(&scope, "command--").unwrap();
549-
keys.sort();
550-
let mut expected = vec![key.clone(), key2.clone()];
551-
expected.sort();
552-
553-
assert_eq!(keys, expected);
554-
assert_eq!(store.keys(&scope, id2.as_str()).unwrap(), [key2.clone()]);
555-
assert_eq!(store.keys(&scope, id3.as_str()).unwrap(), []);
556-
assert_eq!(
557-
store.keys(&Scope::global(), id3.as_str()).unwrap(),
558-
[key3]
559-
);
560-
561-
let mut keys = store.keys(&scope, "").unwrap();
562-
keys.sort();
563-
let mut expected = vec![key, key2];
564-
expected.sort();
565-
566-
assert_eq!(keys, expected);
567-
}
568-
}

0 commit comments

Comments
 (0)