1use std::collections::HashSet;
32
33use yo_common::Result;
34
35use crate::keyspace::Keyspace;
36use crate::scan::Cursor;
37use crate::set::{Member, Set};
38use crate::setops::{self, PerSet};
39use crate::strings;
40use crate::value::{self, Kind};
41
42impl Keyspace {
43 pub fn sadd<'m>(
52 &mut self,
53 key: &[u8],
54 members: impl Iterator<Item = &'m [u8]> + Clone,
55 ) -> Result<usize> {
56 for m in members.clone() {
57 strings::check_len(key, m.len())?;
58 }
59 let at = match self.set_slot(key)? {
60 Some(at) => at,
61 None => {
62 let Some(first) = members.clone().next() else {
68 return Ok(0);
69 };
70 let hint = members.clone().count();
71 self.new_set(key, first, hint)
72 }
73 };
74
75 let limits = self.limits;
78 let set = self
79 .sets
80 .get_mut(at)
81 .expect("the record points at its body");
82 let mut added = 0;
83 for m in members {
84 if set.add(m, &limits) {
85 added += 1;
86 }
87 }
88 Ok(added)
89 }
90
91 pub fn srem<'m>(
95 &mut self,
96 key: &[u8],
97 members: impl Iterator<Item = &'m [u8]>,
98 ) -> Result<usize> {
99 let Some(at) = self.set_slot(key)? else {
100 return Ok(0);
101 };
102 let set = self
103 .sets
104 .get_mut(at)
105 .expect("the record points at its body");
106 let mut gone = 0;
107 for m in members {
108 if set.remove(m) {
109 gone += 1;
110 }
111 }
112 if set.is_empty() {
113 self.drop_key(key);
114 }
115 Ok(gone)
116 }
117
118 pub fn sismember(&mut self, key: &[u8], member: &[u8]) -> Result<bool> {
120 match self.set_slot(key)? {
121 Some(at) => Ok(self.set_at(at).contains(member)),
122 None => Ok(false),
123 }
124 }
125
126 pub fn smismember<'m>(
131 &mut self,
132 key: &[u8],
133 members: impl Iterator<Item = &'m [u8]>,
134 ) -> Result<Vec<bool>> {
135 let Some(at) = self.set_slot(key)? else {
136 return Ok(members.map(|_| false).collect());
137 };
138 let set = self.set_at(at);
139 Ok(members.map(|m| set.contains(m)).collect())
140 }
141
142 pub fn scard(&mut self, key: &[u8]) -> Result<usize> {
144 match self.set_slot(key)? {
145 Some(at) => Ok(self.set_at(at).len()),
146 None => Ok(0),
147 }
148 }
149
150 pub fn smembers(&mut self, key: &[u8]) -> Result<Option<impl Iterator<Item = Member<'_>>>> {
158 let Some(at) = self.set_slot(key)? else {
159 return Ok(None);
160 };
161 Ok(Some(self.set_at(at).iter()))
162 }
163
164 pub fn spop(&mut self, key: &[u8]) -> Result<Option<Vec<u8>>> {
173 let Some(at) = self.set_slot(key)? else {
174 return Ok(None);
175 };
176 let len = self.set_at(at).len();
179 let pick = self.rng.below(len);
180 let got = self
181 .sets
182 .get_mut(at)
183 .expect("the record points at its body")
184 .remove_at(pick);
185 if self.set_at(at).is_empty() {
186 self.drop_key(key);
187 }
188 Ok(got)
189 }
190
191 pub fn spop_n(&mut self, key: &[u8], count: usize) -> Result<Vec<Vec<u8>>> {
200 let Some(at) = self.set_slot(key)? else {
201 return Ok(Vec::new());
202 };
203 let take = count.min(self.set_at(at).len());
204 let mut out = Vec::with_capacity(take);
205 for _ in 0..take {
206 let pick = self.rng.below(self.set_at(at).len());
210 out.push(
211 self.sets
212 .get_mut(at)
213 .expect("the record points at its body")
214 .remove_at(pick)
215 .expect("the draw was under the length"),
216 );
217 }
218 if self.set_at(at).is_empty() {
219 self.drop_key(key);
220 }
221 Ok(out)
222 }
223
224 pub fn spop_into<F>(&mut self, key: &[u8], count: usize, mut f: F) -> Result<usize>
243 where
244 F: FnMut(Member<'_>),
245 {
246 let Some(at) = self.set_slot(key)? else {
247 return Ok(0);
248 };
249 let take = count.min(self.set_at(at).len());
250 for _ in 0..take {
251 let rng = &mut self.rng;
255 let set = self.sets.get(at).expect("the record points at its body");
256 let pick = rng.below(set.len());
257 f(set.at(pick).expect("the draw was under the length"));
258 self.sets
259 .get_mut(at)
260 .expect("the record points at its body")
261 .drop_at(pick);
262 }
263 if self.set_at(at).is_empty() {
264 self.drop_key(key);
265 }
266 Ok(take)
267 }
268
269 pub fn srandmember<R>(
280 &mut self,
281 key: &[u8],
282 f: impl FnOnce(Option<Member<'_>>) -> R,
283 ) -> Result<R> {
284 let Some(at) = self.set_slot(key)? else {
285 return Ok(f(None));
286 };
287 let pick = self.rng.below(self.sets.get(at).expect("a body").len());
288 Ok(f(self.set_at(at).at(pick)))
289 }
290
291 pub fn srandmember_n<F>(&mut self, key: &[u8], count: i64, mut f: F) -> Result<()>
312 where
313 F: FnMut(Member<'_>),
314 {
315 let Some(at) = self.set_slot(key)? else {
316 return Ok(());
317 };
318 let rng = &mut self.rng;
322 let set = self.sets.get(at).expect("the record points at its body");
323 let len = set.len();
324
325 let Ok(want) = usize::try_from(count) else {
326 let repeats = usize::try_from(count.unsigned_abs()).unwrap_or(usize::MAX);
327 for _ in 0..repeats {
328 f(set
329 .at(rng.below(len))
330 .expect("the draw was under the length"));
331 }
332 return Ok(());
333 };
334 if want >= len {
335 for m in set.iter() {
336 f(m);
337 }
338 return Ok(());
339 }
340 if want.saturating_mul(3) > len {
341 let mut need = want;
342 for i in 0..len {
343 if rng.below(len - i) < need {
344 f(set.at(i).expect("i is under the length"));
345 need -= 1;
346 }
347 }
348 return Ok(());
349 }
350 let mut drawn = HashSet::with_capacity(want);
351 while drawn.len() < want {
352 let i = rng.below(len);
353 if drawn.insert(i) {
354 f(set.at(i).expect("the draw was under the length"));
355 }
356 }
357 Ok(())
358 }
359
360 pub fn sscan<F>(&mut self, key: &[u8], cursor: Cursor, count: usize, f: F) -> Result<Cursor>
368 where
369 F: FnMut(Member<'_>),
370 {
371 let Some(at) = self.set_slot(key)? else {
372 return Ok(Cursor::END);
373 };
374 Ok(self.set_at(at).scan(cursor, count, f))
375 }
376
377 pub fn smove(&mut self, source: &[u8], destination: &[u8], member: &[u8]) -> Result<bool> {
389 let Some(from) = self.set_slot(source)? else {
390 return Ok(false);
391 };
392 let onto = self.set_slot(destination)?;
393 if source == destination {
394 return Ok(self.set_at(from).contains(member));
395 }
396 if !self
397 .sets
398 .get_mut(from)
399 .expect("the record points at its body")
400 .remove(member)
401 {
402 return Ok(false);
403 }
404 let limits = self.limits;
408 let at = match onto {
409 Some(at) => at,
410 None => self.new_set(destination, member, 1),
411 };
412 self.sets
413 .get_mut(at)
414 .expect("the record points at its body")
415 .add(member, &limits);
416 if self.set_at(from).is_empty() {
417 self.drop_key(source);
418 }
419 Ok(true)
420 }
421
422 pub fn sinter<'k, F>(
428 &mut self,
429 keys: impl Iterator<Item = &'k [u8]>,
430 limit: usize,
431 f: F,
432 ) -> Result<usize>
433 where
434 F: FnMut(&[u8]),
435 {
436 let slots = self.set_slots(keys)?;
437 if slots.is_empty() || slots.iter().any(Option::is_none) {
441 return Ok(0);
442 }
443 let mut scratch = std::mem::take(&mut self.setops);
446 let sets = self.bodies_of(&slots);
447 let n = setops::inter(&mut scratch, &sets, limit, f);
448 self.setops = scratch;
449 Ok(n)
450 }
451
452 pub fn sintercard<'k>(
454 &mut self,
455 keys: impl Iterator<Item = &'k [u8]>,
456 limit: usize,
457 ) -> Result<usize> {
458 self.sinter(keys, limit, |_| {})
459 }
460
461 pub fn sunion<'k, F>(&mut self, keys: impl Iterator<Item = &'k [u8]>, f: F) -> Result<usize>
468 where
469 F: FnMut(&[u8]),
470 {
471 let slots = self.set_slots(keys)?;
472 let mut scratch = std::mem::take(&mut self.setops);
476 let sets = self.bodies_of(&slots);
477 let n = setops::union(&mut scratch, &sets, f);
478 self.setops = scratch;
479 Ok(n)
480 }
481
482 pub fn sdiff<'k, F>(&mut self, keys: impl Iterator<Item = &'k [u8]>, f: F) -> Result<usize>
488 where
489 F: FnMut(&[u8]),
490 {
491 let slots = self.set_slots(keys)?;
492 let Some(Some(_)) = slots.first() else {
493 return Ok(0);
494 };
495 let sets = self.bodies_of(&slots);
496 Ok(setops::diff(&sets, f))
497 }
498
499 pub fn sinterstore<'k>(
501 &mut self,
502 destination: &[u8],
503 keys: impl Iterator<Item = &'k [u8]>,
504 ) -> Result<usize> {
505 let slots = self.set_slots(keys)?;
506 let mut scratch = std::mem::take(&mut self.setops);
507 let built = if slots.is_empty() || slots.iter().any(Option::is_none) {
508 None
509 } else {
510 let sets = self.bodies_of(&slots);
511 let upper = sets.iter().map(|s| s.len()).min().unwrap_or(0);
513 setops::collect(upper, &self.limits, |f| {
514 setops::inter(&mut scratch, &sets, 0, f);
515 })
516 };
517 self.setops = scratch;
518 Ok(self.put_set(destination, built))
519 }
520
521 pub fn sunionstore<'k>(
523 &mut self,
524 destination: &[u8],
525 keys: impl Iterator<Item = &'k [u8]>,
526 ) -> Result<usize> {
527 let slots = self.set_slots(keys)?;
528 let mut scratch = std::mem::take(&mut self.setops);
529 let built = {
530 let sets = self.bodies_of(&slots);
531 let upper = sets.iter().map(|s| s.len()).sum();
535 setops::collect(upper, &self.limits, |f| {
536 setops::union(&mut scratch, &sets, f);
537 })
538 };
539 self.setops = scratch;
540 Ok(self.put_set(destination, built))
541 }
542
543 pub fn sdiffstore<'k>(
545 &mut self,
546 destination: &[u8],
547 keys: impl Iterator<Item = &'k [u8]>,
548 ) -> Result<usize> {
549 let slots = self.set_slots(keys)?;
550 let built = match slots.first() {
551 Some(Some(_)) => {
552 let sets = self.bodies_of(&slots);
553 let upper = sets[0].len();
554 setops::collect(upper, &self.limits, |f| {
555 setops::diff(&sets, f);
556 })
557 }
558 _ => None,
559 };
560 Ok(self.put_set(destination, built))
561 }
562
563 fn set_slots<'k>(
581 &mut self,
582 keys: impl Iterator<Item = &'k [u8]>,
583 ) -> Result<PerSet<Option<u32>>> {
584 let mut out = PerSet::new();
587 for key in keys {
588 out.push(self.set_slot(key)?);
589 }
590 Ok(out)
591 }
592
593 #[inline]
595 fn bodies_of(&self, slots: &[Option<u32>]) -> PerSet<&Set> {
596 slots.iter().flatten().map(|&at| self.set_at(at)).collect()
597 }
598
599 fn put_set(&mut self, key: &[u8], set: Option<Set>) -> usize {
617 let Some(set) = set else {
618 self.drop_key(key);
619 return 0;
620 };
621 self.free_body(key);
622 let len = set.len();
623 let at = self.sets.insert(set);
624 let record = value::slot_record_len(false);
625 self.write_rec(key, record, |out| {
626 value::write_slot_record(out, Kind::Set, at, None);
627 });
628 self.bodies += 1;
629 len
630 }
631
632 pub fn with_set<R>(&mut self, key: &[u8], f: impl FnOnce(Option<&Set>) -> R) -> Result<R> {
645 let at = self.set_slot(key)?;
646 Ok(f(at.map(|at| self.set_at(at))))
647 }
648
649 fn set_slot(&mut self, key: &[u8]) -> Result<Option<u32>> {
655 self.live_slot(key, Kind::Set)
656 }
657
658 #[inline]
664 fn set_at(&self, at: u32) -> &Set {
665 self.sets.get(at).expect("the record points at its body")
666 }
667
668 fn new_set(&mut self, key: &[u8], first: &[u8], hint: usize) -> u32 {
674 let at =
678 yo_alloc::first_touch(|| self.sets.insert(Set::with_hint(first, hint, &self.limits)));
679 let len = value::slot_record_len(false);
680 self.write_rec(key, len, |out| {
681 value::write_slot_record(out, Kind::Set, at, None);
682 });
683 self.bodies += 1;
684 at
685 }
686}
687
688#[cfg(test)]
689mod tests {
690 use super::*;
691 use crate::Clock;
692 use crate::set::Encoding;
693 use yo_common::Code;
694
695 fn db() -> Keyspace {
696 Keyspace::with_clock(Clock::fixed(1_000))
697 }
698
699 fn add(d: &mut Keyspace, key: &[u8], members: &[&[u8]]) -> usize {
700 d.sadd(key, members.iter().copied()).expect("a set")
701 }
702
703 fn members(d: &mut Keyspace, key: &[u8]) -> Vec<String> {
704 let mut v: Vec<String> = d
705 .smembers(key)
706 .expect("a set")
707 .expect("a key")
708 .map(|m| String::from_utf8(m.to_vec()).expect("utf8 in these tests"))
709 .collect();
710 v.sort();
711 v
712 }
713
714 #[test]
717 fn a_union_over_text_sets_does_not_allocate_once_its_table_is_warm() {
718 let mut d = db();
719 add(&mut d, b"a", &[b"alpha", b"beta", b"gamma", b"delta"]);
720 add(&mut d, b"b", &[b"gamma", b"delta", b"epsilon", b"zeta"]);
721 assert_eq!(d.sunion([b"a".as_slice(), b"b"].into_iter(), |_| {}), Ok(6));
724 let (_, allocs) = crate::tally::counted(|| {
725 for _ in 0..50 {
726 assert_eq!(d.sunion([b"a".as_slice(), b"b"].into_iter(), |_| {}), Ok(6));
727 }
728 });
729 assert_eq!(allocs, 0, "sunion allocated {allocs} times in fifty");
730 }
731
732 #[test]
735 fn a_union_larger_than_the_last_one_grows_the_table_and_is_still_right() {
736 let mut d = db();
737 add(&mut d, b"a", &[b"one", b"two"]);
738 add(&mut d, b"b", &[b"two", b"three"]);
739 assert_eq!(d.sunion([b"a".as_slice(), b"b"].into_iter(), |_| {}), Ok(3));
740
741 let many: Vec<Vec<u8>> = (0..500).map(|i| format!("m{i}").into_bytes()).collect();
742 let refs: Vec<&[u8]> = many.iter().map(Vec::as_slice).collect();
743 add(&mut d, b"c", &refs);
744 let mut seen = Vec::new();
745 assert_eq!(
746 d.sunion([b"a".as_slice(), b"c"].into_iter(), |m| seen
747 .push(m.to_vec())),
748 Ok(502)
749 );
750 seen.sort();
751 seen.dedup();
752 assert_eq!(seen.len(), 502, "every member came back once");
753
754 assert_eq!(d.sunion([b"a".as_slice(), b"b"].into_iter(), |_| {}), Ok(3));
757 }
758
759 #[test]
760 fn adding_to_a_key_that_is_not_there_makes_it() {
761 let mut d = db();
762 assert_eq!(add(&mut d, b"s", &[b"a", b"b", b"c"]), 3);
763 assert_eq!(d.scard(b"s").expect("a set"), 3);
764 assert_eq!(d.kind_of(b"s"), Some(Kind::Set));
765 assert_eq!(members(&mut d, b"s"), ["a", "b", "c"]);
766 assert_eq!(d.len(), 1, "one key, whatever the set holds");
767 }
768
769 #[test]
770 fn adding_answers_how_many_were_new_and_not_how_many_arrived() {
771 let mut d = db();
772 assert_eq!(add(&mut d, b"s", &[b"a", b"b"]), 2);
773 assert_eq!(add(&mut d, b"s", &[b"b", b"c"]), 1);
774 assert_eq!(
775 add(&mut d, b"s", &[b"x", b"x", b"x"]),
776 1,
777 "the same member three times in one call is one member"
778 );
779 assert_eq!(d.scard(b"s").expect("a set"), 4);
780 }
781
782 #[test]
783 fn everything_answers_for_a_key_that_is_not_there() {
784 let mut d = db();
785 assert_eq!(d.scard(b"nope").expect("missing is fine"), 0);
786 assert!(!d.sismember(b"nope", b"a").expect("missing is fine"));
787 assert!(d.smembers(b"nope").expect("missing is fine").is_none());
788 assert_eq!(
789 d.srem(b"nope", [b"a".as_slice()].into_iter()).expect("ok"),
790 0
791 );
792 assert_eq!(
793 d.smismember(b"nope", [b"a".as_slice(), b"b"].into_iter())
794 .expect("ok"),
795 [false, false]
796 );
797 assert_eq!(d.len(), 0, "and none of that created anything");
798 }
799
800 #[test]
801 fn membership_answers_for_members_and_strangers() {
802 let mut d = db();
803 add(&mut d, b"s", &[b"a", b"b"]);
804 assert!(d.sismember(b"s", b"a").expect("a set"));
805 assert!(!d.sismember(b"s", b"z").expect("a set"));
806 assert_eq!(
807 d.smismember(b"s", [b"a".as_slice(), b"z", b"b"].into_iter())
808 .expect("a set"),
809 [true, false, true]
810 );
811 }
812
813 #[test]
814 fn removing_the_last_member_removes_the_key() {
815 let mut d = db();
817 add(&mut d, b"s", &[b"a", b"b"]);
818 assert_eq!(d.srem(b"s", [b"a".as_slice()].into_iter()).expect("ok"), 1);
819 assert!(d.exists(b"s"), "one member left");
820
821 assert_eq!(
822 d.srem(b"s", [b"b".as_slice(), b"gone"].into_iter())
823 .expect("ok"),
824 1,
825 "one of the two was there"
826 );
827 assert!(!d.exists(b"s"), "and now the key is gone with it");
828 assert_eq!(d.kind_of(b"s"), None);
829 assert_eq!(d.len(), 0);
830 }
831
832 #[test]
833 fn a_set_is_deleted_body_and_all() {
834 let mut d = db();
838 add(&mut d, b"s", &[b"a", b"b"]);
839 assert_eq!(d.sets.len(), 1);
840
841 assert!(d.del(b"s"));
842 assert_eq!(d.sets.len(), 0, "the body went with the key");
843 assert_eq!(d.bodies, 0);
844
845 add(&mut d, b"t", &[b"x"]);
847 assert_eq!(d.sets.len(), 1);
848 }
849
850 #[test]
851 fn writing_a_string_over_a_set_takes_the_body_with_it() {
852 let mut d = db();
855 add(&mut d, b"k", &[b"a", b"b"]);
856 assert_eq!(d.sets.len(), 1);
857
858 d.set_plain(b"k", b"now a string").expect("room");
859 assert_eq!(d.sets.len(), 0, "the set went when it was written over");
860 assert_eq!(d.bodies, 0);
861 assert_eq!(d.kind_of(b"k"), Some(Kind::String));
862 assert_eq!(
863 d.get(b"k").expect("a string").map(|v| v.to_vec()),
864 Some(b"now a string".to_vec())
865 );
866 }
867
868 #[test]
869 fn a_set_that_expires_takes_its_body_with_it() {
870 let mut d = db();
871 add(&mut d, b"s", &[b"a"]);
872 assert!(d.set_expiry(b"s", Some(1_100)));
873 assert_eq!(d.expire_at(b"s"), Some(1_100));
874 assert_eq!(d.sets.len(), 1);
875 assert_eq!(d.scard(b"s").expect("a set"), 1, "still alive at 1000");
876
877 d.clock_mut().advance(100);
878 assert_eq!(d.scard(b"s").expect("gone is not an error"), 0);
879 assert_eq!(d.sets.len(), 0, "reaping freed the body");
880 assert_eq!(d.bodies, 0);
881 assert_eq!(d.expired_keys(), 1);
882 }
883
884 #[test]
885 fn flushing_takes_every_body_with_it() {
886 let mut d = db();
887 for i in 0..10 {
888 add(&mut d, format!("s{i}").as_bytes(), &[b"a", b"b"]);
889 }
890 assert_eq!(d.sets.len(), 10);
891
892 d.clear();
893 assert_eq!(d.sets.len(), 0);
894 assert_eq!(d.bodies, 0);
895 assert_eq!(d.len(), 0);
896 }
897
898 #[test]
899 fn a_set_command_at_a_string_is_wrongtype() {
900 let mut d = db();
901 d.set_plain(b"k", b"v").expect("room");
902
903 let err = d.sadd(b"k", [b"a".as_slice()].into_iter()).expect_err("no");
904 assert_eq!(err.code(), Code::WrongType);
905 assert_eq!(
906 err.message(),
907 "Operation against a key holding the wrong kind of value"
908 );
909 assert!(d.scard(b"k").is_err());
910 assert!(d.sismember(b"k", b"a").is_err());
911 assert!(d.smembers(b"k").is_err());
912 assert!(d.srem(b"k", [b"a".as_slice()].into_iter()).is_err());
913 assert!(d.smismember(b"k", [b"a".as_slice()].into_iter()).is_err());
914 assert_eq!(
915 d.get(b"k").expect("still a string").map(|v| v.to_vec()),
916 Some(b"v".to_vec()),
917 "and none of that damaged it"
918 );
919 }
920
921 #[test]
922 fn a_string_command_at_a_set_is_wrongtype() {
923 let mut d = db();
924 add(&mut d, b"s", &[b"a"]);
925
926 assert_eq!(d.get(b"s").expect_err("no").code(), Code::WrongType);
927 assert!(d.strlen(b"s").is_err());
928 assert!(d.getrange(b"s", 0, -1).is_err());
929 assert!(d.getdel(b"s").is_err());
930 assert!(d.incr(b"s").is_err());
931 assert!(d.append(b"s", b"x").is_err());
932 assert_eq!(d.scard(b"s").expect("a set"), 1, "and it is still a set");
933 }
934
935 #[test]
936 fn the_commands_that_do_not_care_still_do_not_care() {
937 let mut d = db();
940 add(&mut d, b"s", &[b"a"]);
941
942 assert!(d.exists(b"s"));
943 assert_eq!(d.kind_of(b"s"), Some(Kind::Set));
944 assert_eq!(d.encoding_name(b"s"), Some("listpack"));
945 assert!(d.set_expiry(b"s", Some(6_000)));
946 assert_eq!(d.expire_at(b"s"), Some(6_000));
947 assert!(d.set_expiry(b"s", None), "and PERSIST takes it off again");
948 assert_eq!(d.expire_at(b"s"), None);
949 assert_eq!(d.scard(b"s").expect("a set"), 1, "through all of that");
950 assert!(d.del(b"s"));
951 }
952
953 #[test]
954 fn mget_says_nil_for_a_set_rather_than_failing() {
955 let mut d = db();
959 d.set_plain(b"a", b"1").expect("room");
960 add(&mut d, b"s", &[b"x"]);
961 d.set_plain(b"z", b"2").expect("room");
962
963 let got: Vec<Option<Vec<u8>>> = d
964 .mget(&[b"a", b"s", b"z", b"nope"])
965 .into_iter()
966 .map(|v| v.map(|s| s.to_vec()))
967 .collect();
968 assert_eq!(got, [Some(b"1".to_vec()), None, Some(b"2".to_vec()), None]);
969 }
970
971 #[test]
972 fn the_representation_follows_the_members_through_the_keyspace() {
973 let mut d = db();
977 add(&mut d, b"s", &[b"1", b"2", b"3"]);
978 assert_eq!(d.set_encoding(b"s"), Some(Encoding::Intset));
979
980 add(&mut d, b"s", &[b"hello"]);
981 assert_eq!(d.set_encoding(b"s"), Some(Encoding::Listpack));
982 assert_eq!(members(&mut d, b"s"), ["1", "2", "3", "hello"]);
983
984 let long: Vec<u8> = vec![b'z'; 100];
985 add(&mut d, b"s", &[&long]);
986 assert_eq!(d.set_encoding(b"s"), Some(Encoding::Hashtable));
987 assert_eq!(d.scard(b"s").expect("a set"), 5);
988 assert!(d.sismember(b"s", b"1").expect("a set"), "nothing was lost");
989 assert!(d.sismember(b"s", &long).expect("a set"));
990 }
991
992 #[test]
993 fn a_thousand_members_at_once_builds_a_table_without_converting() {
994 let mut d = db();
995 let owned: Vec<Vec<u8>> = (0..1000).map(|i| format!("m{i}").into_bytes()).collect();
996 let refs: Vec<&[u8]> = owned.iter().map(Vec::as_slice).collect();
997 assert_eq!(d.sadd(b"s", refs.iter().copied()).expect("a set"), 1000);
998 assert_eq!(d.set_encoding(b"s"), Some(Encoding::Hashtable));
999 assert_eq!(d.scard(b"s").expect("a set"), 1000);
1000 }
1001
1002 fn many(d: &mut Keyspace, key: &[u8], n: usize) {
1004 let owned: Vec<Vec<u8>> = (0..n).map(|i| format!("m{i}").into_bytes()).collect();
1005 let refs: Vec<&[u8]> = owned.iter().map(Vec::as_slice).collect();
1006 d.sadd(key, refs.iter().copied()).expect("a set");
1007 }
1008
1009 fn fill(d: &mut Keyspace, key: &[u8], n: usize, ints: bool) {
1012 let owned: Vec<Vec<u8>> = (0..n)
1013 .map(|i| {
1014 if ints {
1015 i.to_string().into_bytes()
1016 } else {
1017 format!("m{i}").into_bytes()
1018 }
1019 })
1020 .collect();
1021 let refs: Vec<&[u8]> = owned.iter().map(Vec::as_slice).collect();
1022 d.sadd(key, refs.iter().copied()).expect("a set");
1023 }
1024
1025 fn drawn(d: &mut Keyspace, key: &[u8], count: i64) -> Vec<String> {
1026 let mut out = Vec::new();
1027 d.srandmember_n(key, count, |m| {
1028 out.push(String::from_utf8(m.to_vec()).expect("utf8 in these tests"));
1029 })
1030 .expect("a set");
1031 out
1032 }
1033
1034 #[test]
1035 fn popping_takes_a_member_out_and_the_key_with_the_last_one() {
1036 let mut d = db();
1037 add(&mut d, b"s", &[b"a", b"b"]);
1038 let first = d.spop(b"s").expect("a set").expect("two members");
1039 assert_eq!(d.scard(b"s").expect("a set"), 1);
1040
1041 let second = d.spop(b"s").expect("a set").expect("one member");
1042 assert_ne!(first, second, "the same member came back twice");
1043 assert!(!d.exists(b"s"), "the last member took the key");
1044 assert_eq!(d.sets.len(), 0, "and the body");
1045 assert_eq!(d.spop(b"s").expect("gone is not an error"), None);
1046 }
1047
1048 #[test]
1049 fn popping_a_count_empties_a_set_without_repeating_itself() {
1050 for n in [4usize, 100, 300] {
1054 let mut d = db();
1055 many(&mut d, b"s", n);
1056 let got = d.spop_n(b"s", n + 10).expect("a set");
1057 assert_eq!(got.len(), n, "asked for more than there was");
1058 let mut sorted = got.clone();
1059 sorted.sort();
1060 sorted.dedup();
1061 assert_eq!(sorted.len(), n, "a member came back twice");
1062 assert!(!d.exists(b"s"));
1063 assert_eq!(d.sets.len(), 0);
1064 }
1065 }
1066
1067 #[test]
1068 fn popping_part_of_a_set_leaves_the_rest_of_it() {
1069 let mut d = db();
1070 many(&mut d, b"s", 10);
1071 let got = d.spop_n(b"s", 4).expect("a set");
1072 assert_eq!(got.len(), 4);
1073 assert_eq!(d.scard(b"s").expect("a set"), 6);
1074 for m in &got {
1075 assert!(!d.sismember(b"s", m).expect("a set"), "still there");
1076 }
1077 assert_eq!(
1078 d.spop_n(b"s", 0).expect("a set").len(),
1079 0,
1080 "and zero is none"
1081 );
1082 assert_eq!(d.scard(b"s").expect("a set"), 6);
1083 }
1084
1085 #[test]
1086 fn the_borrowing_draw_pops_the_same_set_the_copying_one_does() {
1087 for n in [4usize, 100, 300] {
1091 let mut a = db();
1092 a.seed(20_260_829);
1093 many(&mut a, b"s", n);
1094 let copied = a.spop_n(b"s", n).expect("a set");
1095
1096 let mut b = db();
1097 b.seed(20_260_829);
1098 many(&mut b, b"s", n);
1099 let mut borrowed = Vec::new();
1100 b.spop_into(b"s", n, |m| borrowed.push(m.to_vec()))
1101 .expect("a set");
1102
1103 assert_eq!(copied, borrowed, "{n} members drew differently");
1104 assert!(!b.exists(b"s"), "the last member took the key");
1105 assert_eq!(b.sets.len(), 0, "and the body");
1106 }
1107 }
1108
1109 #[test]
1110 fn the_borrowing_draw_allocates_nothing() {
1111 for n in [4usize, 100, 300] {
1117 for ints in [false, true] {
1118 let mut d = db();
1119 fill(&mut d, b"s", n, ints);
1120 let (drawn, allocs) = crate::tally::counted(|| {
1121 let mut bytes = 0;
1122 let mut count = 0;
1123 d.spop_into(b"s", n, |m| {
1124 bytes += m.byte_len();
1127 count += 1;
1128 })
1129 .expect("a set");
1130 (bytes, count)
1131 });
1132 assert_eq!(drawn.1, n, "{n} members, ints {ints}");
1133 assert!(drawn.0 > 0, "the members came back empty");
1134 assert_eq!(
1135 allocs, 0,
1136 "{n} members, ints {ints}: {allocs} allocations on the way out"
1137 );
1138 }
1139 }
1140 }
1141
1142 #[test]
1153 fn a_small_set_operation_stops_paying_per_key() {
1154 for (ints, want) in [(true, 0), (false, 6)] {
1155 let mut d = db();
1156 fill(&mut d, b"a", 8, ints);
1157 fill(&mut d, b"b", 8, ints);
1158 fill(&mut d, b"c", 8, ints);
1159 let keys: [&[u8]; 3] = [b"a", b"b", b"c"];
1160
1161 let (found, allocs) = crate::tally::counted(|| {
1162 let mut n = 0;
1163 d.sinter(keys.iter().copied(), 0, |_| n += 1).expect("sets");
1164 d.sunion(keys.iter().copied(), |_| n += 1).expect("sets");
1165 d.sdiff(keys.iter().copied(), |_| n += 1).expect("sets");
1166 n
1167 });
1168 assert!(found > 0, "ints {ints}: the operations found nothing");
1169 assert_eq!(
1170 allocs, want,
1171 "ints {ints}: {allocs} allocations for three ops, wanted {want}"
1172 );
1173 }
1174 }
1175
1176 #[test]
1179 fn a_wide_set_operation_still_answers() {
1180 let wide = crate::setops::INLINE_KEYS + 3;
1181 let mut d = db();
1182 let names: Vec<Vec<u8>> = (0..wide).map(|i| format!("k{i}").into_bytes()).collect();
1183 for name in &names {
1184 fill(&mut d, name, 8, true);
1185 }
1186 let keys = || names.iter().map(|k| k.as_slice());
1187 let mut inter = 0;
1188 d.sinter(keys(), 0, |_| inter += 1).expect("sets");
1189 assert_eq!(inter, 8);
1191 let mut union = 0;
1192 d.sunion(keys(), |_| union += 1).expect("sets");
1193 assert_eq!(union, 8);
1194 }
1195
1196 #[test]
1197 fn the_copying_draw_allocates_a_member_at_a_time() {
1198 let mut d = db();
1202 many(&mut d, b"s", 100);
1203 let (got, allocs) = crate::tally::counted(|| d.spop_n(b"s", 100).expect("a set"));
1204 assert_eq!(got.len(), 100);
1205 assert!(allocs >= 100, "only {allocs} allocations for a hundred");
1206 }
1207
1208 #[test]
1209 fn a_pinned_seed_draws_the_same_members_twice() {
1210 let mut runs = Vec::new();
1214 for _ in 0..2 {
1215 let mut d = db();
1216 d.seed(20_260_828);
1217 many(&mut d, b"s", 50);
1218 runs.push(d.spop_n(b"s", 10).expect("a set"));
1219 }
1220 assert_eq!(runs[0], runs[1]);
1221 }
1222
1223 #[test]
1224 fn a_single_draw_reaches_every_member_and_removes_none() {
1225 let mut d = db();
1226 d.seed(7);
1227 add(&mut d, b"s", &[b"a", b"b", b"c"]);
1228 let mut seen = std::collections::HashSet::new();
1229 for _ in 0..200 {
1230 let got = d
1231 .srandmember(b"s", |m| m.map(|m| m.to_vec()))
1232 .expect("a set")
1233 .expect("a member");
1234 seen.insert(got);
1235 }
1236 assert_eq!(seen.len(), 3, "a draw that never reaches a member");
1237 assert_eq!(d.scard(b"s").expect("a set"), 3, "and nothing was taken");
1238
1239 assert!(
1240 d.srandmember(b"nope", |m| m.map(|m| m.to_vec()))
1241 .expect("missing is fine")
1242 .is_none()
1243 );
1244 }
1245
1246 #[test]
1247 fn a_negative_count_repeats_itself_and_a_positive_one_does_not() {
1248 let mut d = db();
1249 d.seed(11);
1250 add(&mut d, b"s", &[b"a", b"b", b"c"]);
1251
1252 let with_repeats = drawn(&mut d, b"s", -20);
1253 assert_eq!(with_repeats.len(), 20, "more members than the set holds");
1254
1255 let mut distinct = drawn(&mut d, b"s", 2);
1256 distinct.sort();
1257 distinct.dedup();
1258 assert_eq!(distinct.len(), 2);
1259 }
1260
1261 #[test]
1262 fn asking_for_more_than_the_set_holds_answers_all_of_it_once() {
1263 let mut d = db();
1264 d.seed(3);
1265 add(&mut d, b"s", &[b"a", b"b", b"c"]);
1266 let mut got = drawn(&mut d, b"s", 99);
1267 got.sort();
1268 assert_eq!(got, ["a", "b", "c"]);
1269 assert_eq!(drawn(&mut d, b"s", 0).len(), 0);
1270 assert_eq!(drawn(&mut d, b"nope", 5).len(), 0);
1271 assert_eq!(drawn(&mut d, b"nope", -5).len(), 0);
1272 }
1273
1274 #[test]
1275 fn both_ways_of_drawing_distinct_members_are_distinct_and_uniform() {
1276 let mut d = db();
1280 d.seed(99);
1281 many(&mut d, b"s", 1000);
1282
1283 for count in [2, 100, 400, 900] {
1284 let got = drawn(&mut d, b"s", count);
1285 let mut sorted = got.clone();
1286 sorted.sort();
1287 sorted.dedup();
1288 assert_eq!(
1289 sorted.len(),
1290 got.len(),
1291 "a draw of {count} repeated a member"
1292 );
1293 assert_eq!(got.len(), count as usize);
1294 }
1295
1296 let mut seen = std::collections::HashSet::new();
1299 for _ in 0..40 {
1300 seen.extend(drawn(&mut d, b"s", 900));
1301 seen.extend(drawn(&mut d, b"s", 2));
1302 }
1303 assert_eq!(seen.len(), 1000, "some member is never drawn");
1304 assert_eq!(d.scard(b"s").expect("a set"), 1000, "and none were taken");
1305 }
1306
1307 #[test]
1308 fn a_scan_walks_a_set_of_any_size_exactly_once() {
1309 for n in [3usize, 100, 500] {
1310 let mut d = db();
1311 many(&mut d, b"s", n);
1312 let mut seen = Vec::new();
1313 let mut c = Cursor::START;
1314 let mut turns = 0;
1315 loop {
1316 c = d
1317 .sscan(b"s", c, 10, |m| seen.push(m.to_vec()))
1318 .expect("a set");
1319 turns += 1;
1320 assert!(turns < 200, "the scan did not finish for {n} members");
1321 if c.is_end() {
1322 break;
1323 }
1324 }
1325 seen.sort();
1326 seen.dedup();
1327 assert_eq!(seen.len(), n, "a scan of {n} members missed one");
1328 }
1329 }
1330
1331 #[test]
1332 fn a_scan_of_a_key_that_is_not_there_is_a_finished_scan() {
1333 let mut d = db();
1334 let mut hit = 0;
1335 let c = d
1336 .sscan(b"nope", Cursor::START, 10, |_| hit += 1)
1337 .expect("ok");
1338 assert!(c.is_end());
1339 assert_eq!(hit, 0);
1340 }
1341
1342 #[test]
1343 fn a_scan_returns_everything_that_was_there_the_whole_time() {
1344 let mut d = db();
1349 many(&mut d, b"s", 500);
1350 let mut seen = Vec::new();
1351 let mut c = Cursor::START;
1352 let mut turns = 0;
1353 loop {
1354 c = d
1355 .sscan(b"s", c, 10, |m| seen.push(m.to_vec()))
1356 .expect("a set");
1357 let victim = format!("m{}", 400 + turns).into_bytes();
1360 d.srem(b"s", [victim.as_slice()].into_iter())
1361 .expect("a set");
1362 turns += 1;
1363 if c.is_end() {
1364 break;
1365 }
1366 }
1367 seen.sort();
1368 seen.dedup();
1369 for i in 0..400 {
1370 let m = format!("m{i}").into_bytes();
1371 assert!(seen.binary_search(&m).is_ok(), "m{i} was never returned");
1372 }
1373 }
1374
1375 #[test]
1376 fn moving_a_member_takes_it_off_one_set_and_puts_it_on_another() {
1377 let mut d = db();
1378 add(&mut d, b"a", &[b"x", b"y"]);
1379 add(&mut d, b"b", &[b"z"]);
1380
1381 assert!(d.smove(b"a", b"b", b"x").expect("two sets"));
1382 assert_eq!(members(&mut d, b"a"), ["y"]);
1383 assert_eq!(members(&mut d, b"b"), ["x", "z"]);
1384
1385 assert!(
1386 !d.smove(b"a", b"b", b"gone").expect("two sets"),
1387 "a member that is not in the source does not move"
1388 );
1389 assert!(
1390 d.smove(b"a", b"b", b"y").expect("two sets"),
1391 "and the last one still moves"
1392 );
1393 assert!(!d.exists(b"a"), "the source went with its last member");
1394 assert_eq!(d.sets.len(), 1, "and so did its body");
1395 assert_eq!(members(&mut d, b"b"), ["x", "y", "z"]);
1396 }
1397
1398 #[test]
1399 fn moving_onto_a_destination_that_is_not_there_makes_it() {
1400 let mut d = db();
1401 add(&mut d, b"a", &[b"x", b"y"]);
1402 assert!(d.smove(b"a", b"b", b"x").expect("a set"));
1403 assert_eq!(d.kind_of(b"b"), Some(Kind::Set));
1404 assert_eq!(members(&mut d, b"b"), ["x"]);
1405 assert_eq!(d.sets.len(), 2);
1406 }
1407
1408 #[test]
1409 fn moving_a_member_onto_its_own_set_changes_nothing() {
1410 let mut d = db();
1411 add(&mut d, b"a", &[b"x", b"y"]);
1412 assert!(d.smove(b"a", b"a", b"x").expect("a set"), "it is there");
1413 assert!(!d.smove(b"a", b"a", b"z").expect("a set"), "it is not");
1414 assert_eq!(members(&mut d, b"a"), ["x", "y"]);
1415 }
1416
1417 #[test]
1418 fn moving_checks_the_types_in_the_order_redis_checks_them() {
1419 let mut d = db();
1420 d.set_plain(b"str", b"v").expect("room");
1421 add(&mut d, b"s", &[b"x"]);
1422
1423 assert!(
1424 !d.smove(b"nope", b"str", b"x").expect("no source, no error"),
1425 "a missing source answers zero without looking at the destination"
1426 );
1427 assert_eq!(
1428 d.smove(b"str", b"s", b"x").expect_err("no").code(),
1429 Code::WrongType
1430 );
1431 assert_eq!(
1432 d.smove(b"s", b"str", b"x").expect_err("no").code(),
1433 Code::WrongType
1434 );
1435 assert_eq!(
1436 members(&mut d, b"s"),
1437 ["x"],
1438 "and the failed move left the source alone"
1439 );
1440 }
1441
1442 #[test]
1443 fn the_new_commands_answer_wrongtype_at_a_string() {
1444 let mut d = db();
1445 d.set_plain(b"k", b"v").expect("room");
1446 assert!(d.spop(b"k").is_err());
1447 assert!(d.spop_n(b"k", 2).is_err());
1448 assert!(d.srandmember(b"k", |m| m.is_some()).is_err());
1449 assert!(d.srandmember_n(b"k", 2, |_| ()).is_err());
1450 assert!(d.sscan(b"k", Cursor::START, 10, |_| ()).is_err());
1451 assert_eq!(
1452 d.get(b"k").expect("still a string").map(|v| v.to_vec()),
1453 Some(b"v".to_vec())
1454 );
1455 }
1456
1457 fn algebra(d: &mut Keyspace, op: &str, keys: &[&[u8]]) -> Vec<String> {
1460 let mut got = Vec::new();
1461 let mut take = |m: &[u8]| got.push(String::from_utf8_lossy(m).into_owned());
1462 let n = match op {
1463 "inter" => d.sinter(keys.iter().copied(), 0, &mut take),
1464 "union" => d.sunion(keys.iter().copied(), &mut take),
1465 "diff" => d.sdiff(keys.iter().copied(), &mut take),
1466 other => unreachable!("{other}"),
1467 }
1468 .expect("sets");
1469 assert_eq!(n, got.len(), "the count and the members disagree");
1470 got.sort();
1471 got
1472 }
1473
1474 #[test]
1475 fn the_algebra_answers_what_the_sets_share_and_do_not() {
1476 let mut d = db();
1477 add(&mut d, b"a", &[b"1", b"2", b"3"]);
1478 add(&mut d, b"b", &[b"2", b"3", b"4"]);
1479 add(&mut d, b"c", &[b"3", b"4", b"5"]);
1480
1481 assert_eq!(algebra(&mut d, "inter", &[b"a", b"b", b"c"]), ["3"]);
1482 assert_eq!(
1483 algebra(&mut d, "union", &[b"a", b"b", b"c"]),
1484 ["1", "2", "3", "4", "5"]
1485 );
1486 assert_eq!(algebra(&mut d, "diff", &[b"a", b"b"]), ["1"]);
1487 assert_eq!(
1488 algebra(&mut d, "diff", &[b"a"]),
1489 ["1", "2", "3"],
1490 "one set is that set"
1491 );
1492 assert_eq!(
1493 d.sintercard([b"a".as_slice(), b"b"].into_iter(), 0)
1494 .expect("sets"),
1495 2
1496 );
1497 assert_eq!(
1498 d.sintercard([b"a".as_slice(), b"b"].into_iter(), 1)
1499 .expect("sets"),
1500 1,
1501 "and a limit stops it early"
1502 );
1503 }
1504
1505 #[test]
1508 fn a_key_that_is_not_there_is_an_empty_set_everywhere() {
1509 let mut d = db();
1510 add(&mut d, b"a", &[b"1", b"2"]);
1511
1512 assert!(algebra(&mut d, "inter", &[b"a", b"nope"]).is_empty());
1513 assert!(algebra(&mut d, "inter", &[b"nope", b"a"]).is_empty());
1514 assert_eq!(algebra(&mut d, "union", &[b"a", b"nope"]), ["1", "2"]);
1515 assert_eq!(algebra(&mut d, "diff", &[b"a", b"nope"]), ["1", "2"]);
1516 assert!(
1517 algebra(&mut d, "diff", &[b"nope", b"a"]).is_empty(),
1518 "nothing minus anything is nothing"
1519 );
1520 assert!(algebra(&mut d, "union", &[b"nope"]).is_empty());
1521 assert_eq!(d.len(), 1, "and none of that made a key");
1522 }
1523
1524 #[test]
1525 fn a_store_form_writes_the_answer_and_says_how_big_it_is() {
1526 let mut d = db();
1527 add(&mut d, b"a", &[b"1", b"2", b"3"]);
1528 add(&mut d, b"b", &[b"2", b"3", b"4"]);
1529
1530 assert_eq!(
1531 d.sinterstore(b"d", [b"a".as_slice(), b"b"].into_iter())
1532 .expect("sets"),
1533 2
1534 );
1535 assert_eq!(members(&mut d, b"d"), ["2", "3"]);
1536 assert_eq!(
1537 d.sunionstore(b"d", [b"a".as_slice(), b"b"].into_iter())
1538 .expect("sets"),
1539 4
1540 );
1541 assert_eq!(members(&mut d, b"d"), ["1", "2", "3", "4"]);
1542 assert_eq!(
1543 d.sdiffstore(b"d", [b"a".as_slice(), b"b"].into_iter())
1544 .expect("sets"),
1545 1
1546 );
1547 assert_eq!(members(&mut d, b"d"), ["1"]);
1548 assert_eq!(d.encoding_name(b"d"), Some(Encoding::Intset.name()));
1551 }
1552
1553 #[test]
1556 fn a_store_form_of_nothing_deletes_the_destination() {
1557 let mut d = db();
1558 add(&mut d, b"a", &[b"1"]);
1559 add(&mut d, b"b", &[b"2"]);
1560 add(&mut d, b"d", &[b"old"]);
1561
1562 assert_eq!(
1563 d.sinterstore(b"d", [b"a".as_slice(), b"b"].into_iter())
1564 .expect("sets"),
1565 0
1566 );
1567 assert_eq!(d.kind_of(b"d"), None, "the destination went, not emptied");
1568 assert!(!d.exists(b"d"));
1569
1570 add(&mut d, b"d", &[b"old"]);
1573 assert_eq!(
1574 d.sdiffstore(b"d", [b"a".as_slice(), b"a"].into_iter())
1575 .expect("sets"),
1576 0
1577 );
1578 assert!(!d.exists(b"d"));
1579 add(&mut d, b"d", &[b"old"]);
1580 assert_eq!(
1581 d.sunionstore(b"d", [b"nope".as_slice()].into_iter())
1582 .expect("sets"),
1583 0
1584 );
1585 assert!(!d.exists(b"d"));
1586 }
1587
1588 #[test]
1591 fn a_store_form_can_write_over_one_of_its_own_sources() {
1592 let mut d = db();
1593 add(&mut d, b"a", &[b"1", b"2", b"3"]);
1594 add(&mut d, b"b", &[b"2", b"3", b"4"]);
1595
1596 assert_eq!(
1597 d.sinterstore(b"a", [b"a".as_slice(), b"b"].into_iter())
1598 .expect("sets"),
1599 2
1600 );
1601 assert_eq!(members(&mut d, b"a"), ["2", "3"]);
1602
1603 assert_eq!(
1605 d.sunionstore(b"a", [b"a".as_slice(), b"a"].into_iter())
1606 .expect("sets"),
1607 2
1608 );
1609 assert_eq!(members(&mut d, b"a"), ["2", "3"]);
1610 }
1611
1612 #[test]
1615 fn a_store_form_overwrites_whatever_the_destination_held() {
1616 let mut d = db();
1617 add(&mut d, b"a", &[b"1", b"2"]);
1618 d.set_plain(b"d", b"a string").expect("room");
1619 assert!(d.set_expiry(b"d", Some(9_999_999)));
1620
1621 assert_eq!(
1622 d.sunionstore(b"d", [b"a".as_slice()].into_iter())
1623 .expect("sets"),
1624 2
1625 );
1626 assert_eq!(d.kind_of(b"d"), Some(Kind::Set));
1627 assert_eq!(members(&mut d, b"d"), ["1", "2"]);
1628 assert_eq!(d.expire_at(b"d"), None, "and the deadline went with it");
1629 }
1630
1631 #[test]
1634 fn the_algebra_answers_wrongtype_before_it_writes_anything() {
1635 let mut d = db();
1636 add(&mut d, b"a", &[b"1"]);
1637 d.set_plain(b"str", b"v").expect("room");
1638 add(&mut d, b"d", &[b"old"]);
1639
1640 assert!(
1641 d.sinter([b"a".as_slice(), b"str"].into_iter(), 0, |_| ())
1642 .is_err()
1643 );
1644 assert!(d.sunion([b"str".as_slice()].into_iter(), |_| ()).is_err());
1645 assert!(
1646 d.sdiff([b"a".as_slice(), b"str"].into_iter(), |_| ())
1647 .is_err()
1648 );
1649 assert!(
1650 d.sinterstore(b"d", [b"a".as_slice(), b"str"].into_iter())
1651 .is_err()
1652 );
1653 assert_eq!(members(&mut d, b"d"), ["old"], "and left it alone");
1654 }
1655
1656 #[test]
1659 fn the_algebra_works_across_the_representations() {
1660 let mut d = db();
1661 let big: Vec<Vec<u8>> = (0..600).map(|i| i.to_string().into_bytes()).collect();
1662 let refs: Vec<&[u8]> = big.iter().map(Vec::as_slice).collect();
1663 d.sadd(b"table", refs.iter().copied()).expect("a set");
1664 add(&mut d, b"ints", &[b"1", b"2", b"999"]);
1665 add(&mut d, b"packed", &[b"2", b"3", b"x"]);
1666 assert_eq!(d.encoding_name(b"table"), Some(Encoding::Hashtable.name()));
1667 assert_eq!(d.encoding_name(b"ints"), Some(Encoding::Intset.name()));
1668 assert_eq!(d.encoding_name(b"packed"), Some(Encoding::Listpack.name()));
1669
1670 assert_eq!(algebra(&mut d, "inter", &[b"ints", b"table"]), ["1", "2"]);
1674 assert_eq!(algebra(&mut d, "inter", &[b"packed", b"table"]), ["2", "3"]);
1675 assert_eq!(algebra(&mut d, "inter", &[b"ints", b"packed"]), ["2"]);
1676 assert_eq!(algebra(&mut d, "diff", &[b"ints", b"table"]), ["999"]);
1677 assert_eq!(
1678 algebra(&mut d, "union", &[b"ints", b"packed"]),
1679 ["1", "2", "3", "999", "x"]
1680 );
1681 }
1682
1683 #[test]
1684 fn a_set_is_counted_in_what_the_database_is_holding() {
1685 let mut d = db();
1686 let before = d.memory_bytes();
1687 let owned: Vec<Vec<u8>> = (0..500).map(|i| i.to_string().into_bytes()).collect();
1688 let refs: Vec<&[u8]> = owned.iter().map(Vec::as_slice).collect();
1689 d.sadd(b"s", refs.iter().copied()).expect("a set");
1690
1691 let after = d.memory_bytes();
1692 assert!(
1693 after > before + 500,
1694 "five hundred members have to show up somewhere: {before} then {after}"
1695 );
1696 d.del(b"s");
1697 assert!(d.memory_bytes() < after, "and go away again");
1698 }
1699
1700 #[test]
1707 fn a_deleted_key_does_not_answer_with_whatever_took_its_slot() {
1708 let mut d = db();
1709 add(&mut d, b"a", &[b"x", b"y", b"z"]);
1710 assert_eq!(d.scard(b"a").expect("a set"), 3);
1711
1712 d.del(b"a");
1713 add(&mut d, b"b", &[b"one"]);
1714
1715 assert_eq!(d.scard(b"a").expect("gone"), 0);
1716 assert!(!d.sismember(b"a", b"x").expect("gone"));
1717 assert_eq!(d.scard(b"b").expect("a set"), 1);
1718 }
1719
1720 #[test]
1724 fn a_key_that_comes_back_as_another_type_is_wrongtype() {
1725 let mut d = db();
1726 add(&mut d, b"k", &[b"x"]);
1727 assert_eq!(d.scard(b"k").expect("a set"), 1);
1728
1729 d.del(b"k");
1730 d.hset(b"k", [(&b"f"[..], &b"v"[..])].into_iter())
1731 .expect("a hash");
1732
1733 let err = d.scard(b"k").expect_err("a hash is not a set");
1734 assert_eq!(err.code(), Code::WrongType);
1735 }
1736
1737 #[test]
1741 fn a_key_with_a_deadline_still_expires_after_it_has_been_read() {
1742 let mut d = db();
1743 add(&mut d, b"k", &[b"x", b"y"]);
1744 assert_eq!(d.scard(b"k").expect("a set"), 2);
1745
1746 assert!(d.set_expiry(b"k", Some(1_500)));
1747 assert_eq!(d.scard(b"k").expect("still alive"), 2);
1748
1749 d.clock_mut().advance(600);
1750 assert_eq!(d.scard(b"k").expect("past its deadline"), 0);
1751 assert!(!d.sismember(b"k", b"x").expect("past its deadline"));
1752 }
1753
1754 #[test]
1758 fn two_keys_in_a_row_do_not_answer_for_each_other() {
1759 let mut d = db();
1760 add(&mut d, b"a", &[b"1"]);
1761 add(&mut d, b"b", &[b"1", b"2", b"3"]);
1762 for _ in 0..8 {
1763 assert_eq!(d.scard(b"a").expect("a set"), 1);
1764 assert_eq!(d.scard(b"b").expect("a set"), 3);
1765 }
1766 }
1767
1768 #[test]
1771 fn a_flush_does_not_leave_the_last_key_behind() {
1772 let mut d = db();
1773 add(&mut d, b"k", &[b"x"]);
1774 assert_eq!(d.scard(b"k").expect("a set"), 1);
1775
1776 d.clear();
1777 assert_eq!(d.scard(b"k").expect("flushed"), 0);
1778 }
1779
1780 #[test]
1784 fn a_key_longer_than_the_memo_still_works() {
1785 let mut d = db();
1786 let long = vec![b'k'; 200];
1787 add(&mut d, &long, &[b"x", b"y"]);
1788 for _ in 0..4 {
1789 assert_eq!(d.scard(&long).expect("a set"), 2);
1790 }
1791 d.del(&long);
1792 assert_eq!(d.scard(&long).expect("gone"), 0);
1793 }
1794}