ソースを参照

Add more tests

Cesar Rodas 3 年 前
コミット
cac07fcea3
5 ファイル変更135 行追加14 行削除
  1. 31 0
      .github/workflows/rust.yml
  2. 42 0
      src/db/entry.rs
  3. 14 13
      src/db/expiration.rs
  4. 41 1
      src/db/mod.rs
  5. 7 0
      src/macros.rs

+ 31 - 0
.github/workflows/rust.yml

@@ -0,0 +1,31 @@
+name: Rust
+
+on:
+  push:
+    branches: [ main, master, develop ]
+  pull_request:
+    branches: [ main, master, develop ]
+
+env:
+  CARGO_TERM_COLOR: always
+
+jobs:
+  build:
+    runs-on: ubuntu-latest
+
+    steps:
+    - uses: actions/checkout@v2
+    - name: Build
+      run: cargo build --verbose
+    - name: Run tests
+      run: cargo test --verbose
+
+  clippy_check:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v1
+      - run: rustup component add clippy
+      - uses: actions-rs/clippy-check@v1
+        with:
+          token: ${{ secrets.GITHUB_TOKEN }}
+          args: --all-features

+ 42 - 0
src/db/entry.rs

@@ -58,3 +58,45 @@ impl Entry {
         self.expires_at.map_or(true, |x| x > Instant::now())
     }
 }
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use tokio::time::Duration;
+
+    #[test]
+    fn is_valid_without_expiration() {
+        let e = Entry::new(Value::Null, None);
+        assert!(e.is_valid());
+    }
+
+    #[test]
+    fn is_valid() {
+        let e = (
+            Entry::new(Value::Null, Some(Instant::now() - Duration::from_secs(5))),
+            Entry::new(Value::Null, Some(Instant::now())),
+            Entry::new(Value::Null, Some(Instant::now() + Duration::from_secs(5))),
+        );
+        assert!(!e.0.is_valid());
+        assert!(!e.1.is_valid());
+        assert!(e.2.is_valid());
+    }
+
+    #[test]
+    fn persist() {
+        let mut e = Entry::new(Value::Null, Some(Instant::now()));
+        assert!(!e.is_valid());
+        e.persist();
+        assert!(e.is_valid());
+    }
+
+    #[test]
+    fn update_ttl() {
+        let mut e = Entry::new(Value::Null, Some(Instant::now()));
+        assert!(!e.is_valid());
+        e.persist();
+        assert!(e.is_valid());
+        e.set_ttl(Instant::now());
+        assert!(!e.is_valid());
+    }
+}

+ 14 - 13
src/db/expiration.rs

@@ -90,14 +90,15 @@ impl ExpirationDb {
 #[cfg(test)]
 mod test {
     use super::*;
+    use crate::bytes;
     use tokio::time::{Duration, Instant};
 
     #[test]
     fn two_entires_same_expiration() {
         let mut db = ExpirationDb::new();
-        let key1 = Bytes::from(&b"key"[..]);
-        let key2 = Bytes::from(&b"bar"[..]);
-        let key3 = Bytes::from(&b"xxx"[..]);
+        let key1 = bytes!(b"key");
+        let key2 = bytes!(b"bar");
+        let key3 = bytes!(b"xxx");
         let expiration = Instant::now() + Duration::from_secs(5);
 
         db.add(&key1, expiration);
@@ -110,8 +111,8 @@ mod test {
     #[test]
     fn remove_prev_expiration() {
         let mut db = ExpirationDb::new();
-        let key1 = Bytes::from(&b"key"[..]);
-        let key2 = Bytes::from(&b"bar"[..]);
+        let key1 = bytes!(b"key");
+        let key2 = bytes!(b"bar");
         let expiration = Instant::now() + Duration::from_secs(5);
 
         db.add(&key1, expiration);
@@ -126,19 +127,19 @@ mod test {
         let mut db = ExpirationDb::new();
         let keys = vec![
             (
-                Bytes::from(&b"hix"[..]),
+                bytes!(b"hix"),
                 Instant::now() + Duration::from_secs(15),
             ),
             (
-                Bytes::from(&b"key"[..]),
+                bytes!(b"key"),
                 Instant::now() + Duration::from_secs(2),
             ),
             (
-                Bytes::from(&b"bar"[..]),
+                bytes!(b"bar"),
                 Instant::now() + Duration::from_secs(3),
             ),
             (
-                Bytes::from(&b"hi"[..]),
+                bytes!(b"hi"),
                 Instant::now() + Duration::from_secs(3),
             ),
         ];
@@ -172,19 +173,19 @@ mod test {
         let mut db = ExpirationDb::new();
         let keys = vec![
             (
-                Bytes::from(&b"hix"[..]),
+                bytes!(b"hix"),
                 Instant::now() + Duration::from_secs(15),
             ),
             (
-                Bytes::from(&b"key"[..]),
+                bytes!(b"key"),
                 Instant::now() + Duration::from_secs(2),
             ),
             (
-                Bytes::from(&b"bar"[..]),
+                bytes!(b"bar"),
                 Instant::now() + Duration::from_secs(3),
             ),
             (
-                Bytes::from(&b"hi"[..]),
+                bytes!(b"hi"),
                 Instant::now() + Duration::from_secs(3),
             ),
         ];

+ 41 - 1
src/db/mod.rs

@@ -198,8 +198,9 @@ impl Db {
             .map(|x| x.get_ttl())
     }
 
-    pub fn purge(&self) {
+    pub fn purge(&self) -> u64 {
         let mut expirations = self.expirations.lock().unwrap();
+        let mut removed = 0;
 
         trace!("Watching {} keys for expirations", expirations.len());
 
@@ -211,8 +212,47 @@ impl Db {
                 let mut entries = self.entries[self.get_slot(key)].write().unwrap();
                 if entries.remove(key).is_some() {
                     trace!("Removed key {:?} due timeout", key);
+                    removed += 1;
                 }
             })
             .for_each(drop);
+
+        removed
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use crate::bytes;
+
+    #[test]
+    fn purge_keys() {
+        let db = Db::new(100);
+        db.set(& bytes!(b"one"), &Value::OK, Some(Duration::from_secs(0)));
+        // Expired keys should not be returned, even if they are not yet
+        // removed by the purge process.
+        assert_eq!(Value::Null, db.get(& bytes!(b"one")));
+
+        // Purge twice
+        assert_eq!(1, db.purge());
+        assert_eq!(0, db.purge());
+
+        assert_eq!(Value::Null, db.get(& bytes!(b"one")));
+    }
+
+    #[test]
+    fn replace_purge_keys() {
+        let db = Db::new(100);
+        db.set(& bytes!(b"one"), &Value::OK, Some(Duration::from_secs(0)));
+        // Expired keys should not be returned, even if they are not yet
+        // removed by the purge process.
+        assert_eq!(Value::Null, db.get(& bytes!(b"one")));
+
+        db.set(& bytes!(b"one"), &Value::OK, Some(Duration::from_secs(5)));
+        assert_eq!(Value::OK, db.get(& bytes!(b"one")));
+
+        // Purge should return 0 as the expired key has been removed already
+        assert_eq!(0, db.purge());
     }
 }

+ 7 - 0
src/macros.rs

@@ -151,3 +151,10 @@ macro_rules! check_arg {
         }
     }}
 }
+
+#[macro_export]
+macro_rules! bytes {
+    ($content:tt) => {
+        Bytes::from(& $content [..])
+    }
+}