1use std::collections::HashSet;
32
33use yo_common::Result;
34
35use crate::db::{Db, Holds};
36use crate::keyspace::Keyspace;
37use crate::scan::Cursor;
38use crate::set::{Member, Set};
39use crate::setops::{self, PerSet};
40use crate::strings;
41use crate::value::{self, Kind};
42
43impl Keyspace {
44 pub fn sadd<'m>(
53 &mut self,
54 key: &[u8],
55 members: impl Iterator<Item = &'m [u8]> + Clone,
56 ) -> Result<usize> {
57 for m in members.clone() {
58 strings::check_len(key, m.len())?;
59 }
60 let at = match self.set_slot(key)? {
61 Some(at) => at,
62 None => {
63 let Some(first) = members.clone().next() else {
69 return Ok(0);
70 };
71 let hint = members.clone().count();
72 self.new_set(key, first, hint)
73 }
74 };
75
76 let limits = self.limits;
79 let set = self
80 .sets
81 .get_mut(at)
82 .expect("the record points at its body");
83 let mut added = 0;
84 for m in members {
85 if set.add(m, &limits) {
86 added += 1;
87 }
88 }
89 Ok(added)
90 }
91
92 pub fn srem<'m>(
96 &mut self,
97 key: &[u8],
98 members: impl Iterator<Item = &'m [u8]>,
99 ) -> Result<usize> {
100 let Some(at) = self.set_slot(key)? else {
101 return Ok(0);
102 };
103 let set = self
104 .sets
105 .get_mut(at)
106 .expect("the record points at its body");
107 let mut gone = 0;
108 for m in members {
109 if set.remove(m) {
110 gone += 1;
111 }
112 }
113 if set.is_empty() {
114 self.drop_key(key);
115 }
116 Ok(gone)
117 }
118
119 pub fn sismember(&mut self, key: &[u8], member: &[u8]) -> Result<bool> {
121 match self.set_slot(key)? {
122 Some(at) => Ok(self.set_at(at).contains(member)),
123 None => Ok(false),
124 }
125 }
126
127 pub fn smismember<'m>(
132 &mut self,
133 key: &[u8],
134 members: impl Iterator<Item = &'m [u8]>,
135 ) -> Result<Vec<bool>> {
136 let Some(at) = self.set_slot(key)? else {
137 return Ok(members.map(|_| false).collect());
138 };
139 let set = self.set_at(at);
140 Ok(members.map(|m| set.contains(m)).collect())
141 }
142
143 pub fn scard(&mut self, key: &[u8]) -> Result<usize> {
145 match self.set_slot(key)? {
146 Some(at) => Ok(self.set_at(at).len()),
147 None => Ok(0),
148 }
149 }
150
151 pub fn smembers(&mut self, key: &[u8]) -> Result<Option<impl Iterator<Item = Member<'_>>>> {
159 let Some(at) = self.set_slot(key)? else {
160 return Ok(None);
161 };
162 Ok(Some(self.set_at(at).iter()))
163 }
164
165 pub fn spop(&mut self, key: &[u8]) -> Result<Option<Vec<u8>>> {
174 let Some(at) = self.set_slot(key)? else {
175 return Ok(None);
176 };
177 let len = self.set_at(at).len();
180 let pick = self.rng.below(len);
181 let got = self
182 .sets
183 .get_mut(at)
184 .expect("the record points at its body")
185 .remove_at(pick);
186 if self.set_at(at).is_empty() {
187 self.drop_key(key);
188 }
189 Ok(got)
190 }
191
192 pub fn spop_n(&mut self, key: &[u8], count: usize) -> Result<Vec<Vec<u8>>> {
201 let Some(at) = self.set_slot(key)? else {
202 return Ok(Vec::new());
203 };
204 let take = count.min(self.set_at(at).len());
205 let mut out = Vec::with_capacity(take);
206 for _ in 0..take {
207 let pick = self.rng.below(self.set_at(at).len());
211 out.push(
212 self.sets
213 .get_mut(at)
214 .expect("the record points at its body")
215 .remove_at(pick)
216 .expect("the draw was under the length"),
217 );
218 }
219 if self.set_at(at).is_empty() {
220 self.drop_key(key);
221 }
222 Ok(out)
223 }
224
225 pub fn spop_into<F>(&mut self, key: &[u8], count: usize, mut f: F) -> Result<usize>
244 where
245 F: FnMut(Member<'_>),
246 {
247 let Some(at) = self.set_slot(key)? else {
248 return Ok(0);
249 };
250 let take = count.min(self.set_at(at).len());
251 for _ in 0..take {
252 let rng = &mut self.rng;
256 let set = self.sets.get(at).expect("the record points at its body");
257 let pick = rng.below(set.len());
258 f(set.at(pick).expect("the draw was under the length"));
259 self.sets
260 .get_mut(at)
261 .expect("the record points at its body")
262 .drop_at(pick);
263 }
264 if self.set_at(at).is_empty() {
265 self.drop_key(key);
266 }
267 Ok(take)
268 }
269
270 pub fn srandmember<R>(
281 &mut self,
282 key: &[u8],
283 f: impl FnOnce(Option<Member<'_>>) -> R,
284 ) -> Result<R> {
285 let Some(at) = self.set_slot(key)? else {
286 return Ok(f(None));
287 };
288 let pick = self.rng.below(self.sets.get(at).expect("a body").len());
289 Ok(f(self.set_at(at).at(pick)))
290 }
291
292 pub fn srandmember_n<F>(&mut self, key: &[u8], count: i64, mut f: F) -> Result<()>
313 where
314 F: FnMut(Member<'_>),
315 {
316 let Some(at) = self.set_slot(key)? else {
317 return Ok(());
318 };
319 let rng = &mut self.rng;
323 let set = self.sets.get(at).expect("the record points at its body");
324 let len = set.len();
325
326 let Ok(want) = usize::try_from(count) else {
327 let repeats = usize::try_from(count.unsigned_abs()).unwrap_or(usize::MAX);
328 for _ in 0..repeats {
329 f(set
330 .at(rng.below(len))
331 .expect("the draw was under the length"));
332 }
333 return Ok(());
334 };
335 if want >= len {
336 for m in set.iter() {
337 f(m);
338 }
339 return Ok(());
340 }
341 if want.saturating_mul(3) > len {
342 let mut need = want;
343 for i in 0..len {
344 if rng.below(len - i) < need {
345 f(set.at(i).expect("i is under the length"));
346 need -= 1;
347 }
348 }
349 return Ok(());
350 }
351 let mut drawn = HashSet::with_capacity(want);
352 while drawn.len() < want {
353 let i = rng.below(len);
354 if drawn.insert(i) {
355 f(set.at(i).expect("the draw was under the length"));
356 }
357 }
358 Ok(())
359 }
360
361 pub fn sscan<F>(&mut self, key: &[u8], cursor: Cursor, count: usize, f: F) -> Result<Cursor>
369 where
370 F: FnMut(Member<'_>),
371 {
372 let Some(at) = self.set_slot(key)? else {
373 return Ok(Cursor::END);
374 };
375 Ok(self.set_at(at).scan(cursor, count, f))
376 }
377
378 pub fn smove(&mut self, source: &[u8], destination: &[u8], member: &[u8]) -> Result<bool> {
390 let Some(from) = self.set_slot(source)? else {
391 return Ok(false);
392 };
393 let onto = self.set_slot(destination)?;
394 if source == destination {
395 return Ok(self.set_at(from).contains(member));
396 }
397 if !self
398 .sets
399 .get_mut(from)
400 .expect("the record points at its body")
401 .remove(member)
402 {
403 return Ok(false);
404 }
405 let limits = self.limits;
409 let at = match onto {
410 Some(at) => at,
411 None => self.new_set(destination, member, 1),
412 };
413 self.sets
414 .get_mut(at)
415 .expect("the record points at its body")
416 .add(member, &limits);
417 if self.set_at(from).is_empty() {
418 self.drop_key(source);
419 }
420 Ok(true)
421 }
422
423 pub fn sinter<'k, F>(
429 &mut self,
430 keys: impl Iterator<Item = &'k [u8]>,
431 limit: usize,
432 f: F,
433 ) -> Result<usize>
434 where
435 F: FnMut(&[u8]),
436 {
437 let slots = self.set_slots(keys)?;
438 if slots.is_empty() || slots.iter().any(Option::is_none) {
442 return Ok(0);
443 }
444 let mut scratch = std::mem::take(&mut self.setops);
447 let sets = self.bodies_of(&slots);
448 let n = setops::inter(&mut scratch, &sets, limit, f);
449 self.setops = scratch;
450 Ok(n)
451 }
452
453 pub fn sintercard<'k>(
455 &mut self,
456 keys: impl Iterator<Item = &'k [u8]>,
457 limit: usize,
458 ) -> Result<usize> {
459 self.sinter(keys, limit, |_| {})
460 }
461
462 pub fn sunion<'k, F>(
471 &mut self,
472 keys: impl Iterator<Item = &'k [u8]>,
473 limit: usize,
474 f: F,
475 ) -> Result<usize>
476 where
477 F: FnMut(&[u8]),
478 {
479 let slots = self.set_slots(keys)?;
480 let mut scratch = std::mem::take(&mut self.setops);
484 let sets = self.bodies_of(&slots);
485 let n = setops::union(&mut scratch, &sets, limit, f);
486 self.setops = scratch;
487 Ok(n)
488 }
489
490 pub fn sunioncard<'k>(
492 &mut self,
493 keys: impl Iterator<Item = &'k [u8]>,
494 limit: usize,
495 ) -> Result<usize> {
496 self.sunion(keys, limit, |_| {})
497 }
498
499 pub fn sdiff<'k, F>(
505 &mut self,
506 keys: impl Iterator<Item = &'k [u8]>,
507 limit: usize,
508 f: F,
509 ) -> Result<usize>
510 where
511 F: FnMut(&[u8]),
512 {
513 let slots = self.set_slots(keys)?;
514 let Some(Some(_)) = slots.first() else {
515 return Ok(0);
516 };
517 let sets = self.bodies_of(&slots);
518 Ok(setops::diff(&sets, limit, f))
519 }
520
521 pub fn sdiffcard<'k>(
523 &mut self,
524 keys: impl Iterator<Item = &'k [u8]>,
525 limit: usize,
526 ) -> Result<usize> {
527 self.sdiff(keys, limit, |_| {})
528 }
529
530 pub fn sinterstore<'k>(
532 &mut self,
533 destination: &[u8],
534 keys: impl Iterator<Item = &'k [u8]>,
535 ) -> Result<usize> {
536 let slots = self.set_slots(keys)?;
537 let mut scratch = std::mem::take(&mut self.setops);
538 let built = if slots.is_empty() || slots.iter().any(Option::is_none) {
539 None
540 } else {
541 let sets = self.bodies_of(&slots);
542 let upper = sets.iter().map(|s| s.len()).min().unwrap_or(0);
544 setops::collect(upper, &self.limits, |f| {
545 setops::inter(&mut scratch, &sets, 0, f);
546 })
547 };
548 self.setops = scratch;
549 Ok(self.put_set(destination, built))
550 }
551
552 pub fn sunionstore<'k>(
554 &mut self,
555 destination: &[u8],
556 keys: impl Iterator<Item = &'k [u8]>,
557 ) -> Result<usize> {
558 let slots = self.set_slots(keys)?;
559 let mut scratch = std::mem::take(&mut self.setops);
560 let built = {
561 let sets = self.bodies_of(&slots);
562 let upper = sets.iter().map(|s| s.len()).sum();
566 setops::collect(upper, &self.limits, |f| {
567 setops::union(&mut scratch, &sets, 0, f);
568 })
569 };
570 self.setops = scratch;
571 Ok(self.put_set(destination, built))
572 }
573
574 pub fn sdiffstore<'k>(
576 &mut self,
577 destination: &[u8],
578 keys: impl Iterator<Item = &'k [u8]>,
579 ) -> Result<usize> {
580 let slots = self.set_slots(keys)?;
581 let built = match slots.first() {
582 Some(Some(_)) => {
583 let sets = self.bodies_of(&slots);
584 let upper = sets[0].len();
585 setops::collect(upper, &self.limits, |f| {
586 setops::diff(&sets, 0, f);
587 })
588 }
589 _ => None,
590 };
591 Ok(self.put_set(destination, built))
592 }
593
594 fn set_slots<'k>(
612 &mut self,
613 keys: impl Iterator<Item = &'k [u8]>,
614 ) -> Result<PerSet<Option<u32>>> {
615 let mut out = PerSet::new();
618 for key in keys {
619 out.push(self.set_slot(key)?);
620 }
621 Ok(out)
622 }
623
624 #[inline]
626 fn bodies_of(&self, slots: &[Option<u32>]) -> PerSet<&Set> {
627 slots.iter().flatten().map(|&at| self.set_at(at)).collect()
628 }
629
630 fn put_set(&mut self, key: &[u8], set: Option<Set>) -> usize {
648 let Some(set) = set else {
649 self.drop_key(key);
650 return 0;
651 };
652 self.replacing(key, Kind::Set);
653 self.free_body(key);
654 let len = set.len();
655 let at = self.sets.insert(set);
656 let record = value::slot_record_len(false);
657 self.write_rec(key, record, |out| {
658 value::write_slot_record(out, Kind::Set, at, None);
659 });
660 self.bodies += 1;
661 len
662 }
663
664 pub fn with_set<R>(&mut self, key: &[u8], f: impl FnOnce(Option<&Set>) -> R) -> Result<R> {
677 let at = self.set_slot(key)?;
678 Ok(f(at.map(|at| self.set_at(at))))
679 }
680
681 fn set_slot(&mut self, key: &[u8]) -> Result<Option<u32>> {
687 self.live_slot(key, Kind::Set)
688 }
689
690 #[inline]
696 fn set_at(&self, at: u32) -> &Set {
697 self.sets.get(at).expect("the record points at its body")
698 }
699
700 fn new_set(&mut self, key: &[u8], first: &[u8], hint: usize) -> u32 {
706 let at =
710 yo_alloc::first_touch(|| self.sets.insert(Set::with_hint(first, hint, &self.limits)));
711 let len = value::slot_record_len(false);
712 self.write_rec(key, len, |out| {
713 value::write_slot_record(out, Kind::Set, at, None);
714 });
715 self.bodies += 1;
716 at
717 }
718}
719
720type Home = (usize, u32);
726
727impl Db {
728 pub fn smove(&self, source: &[u8], destination: &[u8], member: &[u8]) -> Result<bool> {
741 let (from, onto) = (self.stripe_of(source), self.stripe_of(destination));
742 if from == onto {
743 return self.hold_stripe(from).smove(source, destination, member);
744 }
745 let mut held = self.hold_many([from, onto].into_iter());
749 let Some(at) = held.stripe_mut(from).set_slot(source)? else {
750 return Ok(false);
751 };
752 let there = held.stripe_mut(onto).set_slot(destination)?;
753 if !held
754 .stripe_mut(from)
755 .sets
756 .get_mut(at)
757 .expect("the record points at its body")
758 .remove(member)
759 {
760 return Ok(false);
761 }
762
763 let dest = held.stripe_mut(onto);
764 let limits = dest.limits;
765 let into = match there {
766 Some(into) => into,
767 None => dest.new_set(destination, member, 1),
768 };
769 dest.sets
770 .get_mut(into)
771 .expect("the record points at its body")
772 .add(member, &limits);
773
774 let src = held.stripe_mut(from);
775 if src.set_at(at).is_empty() {
776 src.drop_key(source);
777 }
778 Ok(true)
779 }
780
781 pub fn sinter<'k, F>(
783 &self,
784 keys: impl Iterator<Item = &'k [u8]> + Clone,
785 limit: usize,
786 f: F,
787 ) -> Result<usize>
788 where
789 F: FnMut(&[u8]),
790 {
791 if let Some(home) = self.one_stripe(keys.clone()) {
792 return self.hold_stripe(home).sinter(keys, limit, f);
793 }
794 let mut spare = self.spare();
797 let scratch = &mut spare.setops;
798 let mut held = self.hold_sets(keys.clone(), None);
799 let slots = self.set_slots(&mut held, keys)?;
800 if slots.is_empty() || slots.iter().any(Option::is_none) {
801 return Ok(0);
802 }
803 let sets = bodies_of(&held, &slots);
804 Ok(setops::inter(scratch, &sets, limit, f))
805 }
806
807 pub fn sintercard<'k>(
809 &self,
810 keys: impl Iterator<Item = &'k [u8]> + Clone,
811 limit: usize,
812 ) -> Result<usize> {
813 self.sinter(keys, limit, |_| {})
814 }
815
816 pub fn sunion<'k, F>(
818 &self,
819 keys: impl Iterator<Item = &'k [u8]> + Clone,
820 limit: usize,
821 f: F,
822 ) -> Result<usize>
823 where
824 F: FnMut(&[u8]),
825 {
826 if let Some(home) = self.one_stripe(keys.clone()) {
827 return self.hold_stripe(home).sunion(keys, limit, f);
828 }
829 let mut spare = self.spare();
832 let scratch = &mut spare.setops;
833 let mut held = self.hold_sets(keys.clone(), None);
834 let slots = self.set_slots(&mut held, keys)?;
835 let sets = bodies_of(&held, &slots);
836 Ok(setops::union(scratch, &sets, limit, f))
837 }
838
839 pub fn sunioncard<'k>(
841 &self,
842 keys: impl Iterator<Item = &'k [u8]> + Clone,
843 limit: usize,
844 ) -> Result<usize> {
845 self.sunion(keys, limit, |_| {})
846 }
847
848 pub fn sdiff<'k, F>(
850 &self,
851 keys: impl Iterator<Item = &'k [u8]> + Clone,
852 limit: usize,
853 f: F,
854 ) -> Result<usize>
855 where
856 F: FnMut(&[u8]),
857 {
858 if let Some(home) = self.one_stripe(keys.clone()) {
859 return self.hold_stripe(home).sdiff(keys, limit, f);
860 }
861 let mut held = self.hold_sets(keys.clone(), None);
862 let slots = self.set_slots(&mut held, keys)?;
863 let Some(Some(_)) = slots.first() else {
864 return Ok(0);
865 };
866 let sets = bodies_of(&held, &slots);
867 Ok(setops::diff(&sets, limit, f))
868 }
869
870 pub fn sdiffcard<'k>(
872 &self,
873 keys: impl Iterator<Item = &'k [u8]> + Clone,
874 limit: usize,
875 ) -> Result<usize> {
876 self.sdiff(keys, limit, |_| {})
877 }
878
879 pub fn sinterstore<'k>(
886 &self,
887 destination: &'k [u8],
888 keys: impl Iterator<Item = &'k [u8]> + Clone,
889 ) -> Result<usize> {
890 if let Some(home) = self.one_stripe(std::iter::once(destination).chain(keys.clone())) {
891 return self.hold_stripe(home).sinterstore(destination, keys);
892 }
893 let mut spare = self.spare();
896 let scratch = &mut spare.setops;
897 let onto = self.stripe_of(destination);
898 let mut held = self.hold_sets(keys.clone(), Some(destination));
899 let slots = self.set_slots(&mut held, keys)?;
900 let built = if slots.is_empty() || slots.iter().any(Option::is_none) {
901 None
902 } else {
903 let limits = held.stripe(onto).limits;
904 let sets = bodies_of(&held, &slots);
905 let upper = sets.iter().map(|s| s.len()).min().unwrap_or(0);
906 setops::collect(upper, &limits, |f| {
907 setops::inter(scratch, &sets, 0, f);
908 })
909 };
910 Ok(held.stripe_mut(onto).put_set(destination, built))
911 }
912
913 pub fn sunionstore<'k>(
915 &self,
916 destination: &'k [u8],
917 keys: impl Iterator<Item = &'k [u8]> + Clone,
918 ) -> Result<usize> {
919 if let Some(home) = self.one_stripe(std::iter::once(destination).chain(keys.clone())) {
920 return self.hold_stripe(home).sunionstore(destination, keys);
921 }
922 let mut spare = self.spare();
925 let scratch = &mut spare.setops;
926 let onto = self.stripe_of(destination);
927 let mut held = self.hold_sets(keys.clone(), Some(destination));
928 let slots = self.set_slots(&mut held, keys)?;
929 let built = {
930 let limits = held.stripe(onto).limits;
931 let sets = bodies_of(&held, &slots);
932 let upper = sets.iter().map(|s| s.len()).sum();
933 setops::collect(upper, &limits, |f| {
934 setops::union(scratch, &sets, 0, f);
935 })
936 };
937 Ok(held.stripe_mut(onto).put_set(destination, built))
938 }
939
940 pub fn sdiffstore<'k>(
942 &self,
943 destination: &'k [u8],
944 keys: impl Iterator<Item = &'k [u8]> + Clone,
945 ) -> Result<usize> {
946 if let Some(home) = self.one_stripe(std::iter::once(destination).chain(keys.clone())) {
947 return self.hold_stripe(home).sdiffstore(destination, keys);
948 }
949 let onto = self.stripe_of(destination);
950 let mut held = self.hold_sets(keys.clone(), Some(destination));
951 let slots = self.set_slots(&mut held, keys)?;
952 let built = match slots.first() {
953 Some(Some(_)) => {
954 let limits = held.stripe(onto).limits;
955 let sets = bodies_of(&held, &slots);
956 let upper = sets[0].len();
957 setops::collect(upper, &limits, |f| {
958 setops::diff(&sets, 0, f);
959 })
960 }
961 _ => None,
962 };
963 Ok(held.stripe_mut(onto).put_set(destination, built))
964 }
965
966 #[inline]
974 fn hold_sets<'k>(
975 &self,
976 keys: impl Iterator<Item = &'k [u8]>,
977 destination: Option<&[u8]>,
978 ) -> Holds<'_> {
979 let named = keys.map(|key| self.stripe_of(key));
980 self.hold_many(named.chain(destination.map(|d| self.stripe_of(d))))
981 }
982
983 fn set_slots<'k>(
991 &self,
992 held: &mut Holds<'_>,
993 keys: impl Iterator<Item = &'k [u8]>,
994 ) -> Result<PerSet<Option<Home>>> {
995 let mut out = PerSet::new();
996 for key in keys {
997 let stripe = self.stripe_of(key);
998 let at = held.stripe_mut(stripe).set_slot(key)?;
999 out.push(at.map(|at| (stripe, at)));
1000 }
1001 Ok(out)
1002 }
1003}
1004
1005#[inline]
1007fn bodies_of<'h>(held: &'h Holds<'_>, slots: &[Option<Home>]) -> PerSet<&'h Set> {
1008 slots
1009 .iter()
1010 .flatten()
1011 .map(|&(stripe, at)| held.stripe(stripe).set_at(at))
1012 .collect()
1013}
1014
1015#[cfg(test)]
1016mod tests {
1017 use super::*;
1018 use crate::Clock;
1019 use crate::set::Encoding;
1020 use yo_common::Code;
1021
1022 fn db() -> Keyspace {
1023 Keyspace::with_clock(Clock::fixed(1_000))
1024 }
1025
1026 fn add(d: &mut Keyspace, key: &[u8], members: &[&[u8]]) -> usize {
1027 d.sadd(key, members.iter().copied()).expect("a set")
1028 }
1029
1030 fn members(d: &mut Keyspace, key: &[u8]) -> Vec<String> {
1031 let mut v: Vec<String> = d
1032 .smembers(key)
1033 .expect("a set")
1034 .expect("a key")
1035 .map(|m| String::from_utf8(m.to_vec()).expect("utf8 in these tests"))
1036 .collect();
1037 v.sort();
1038 v
1039 }
1040
1041 #[test]
1044 fn a_union_over_text_sets_does_not_allocate_once_its_table_is_warm() {
1045 let mut d = db();
1046 add(&mut d, b"a", &[b"alpha", b"beta", b"gamma", b"delta"]);
1047 add(&mut d, b"b", &[b"gamma", b"delta", b"epsilon", b"zeta"]);
1048 assert_eq!(
1051 d.sunion([b"a".as_slice(), b"b"].into_iter(), 0, |_| {}),
1052 Ok(6)
1053 );
1054 let (_, allocs) = crate::tally::counted(|| {
1055 for _ in 0..50 {
1056 assert_eq!(
1057 d.sunion([b"a".as_slice(), b"b"].into_iter(), 0, |_| {}),
1058 Ok(6)
1059 );
1060 }
1061 });
1062 assert_eq!(allocs, 0, "sunion allocated {allocs} times in fifty");
1063 }
1064
1065 #[test]
1068 fn a_union_larger_than_the_last_one_grows_the_table_and_is_still_right() {
1069 let mut d = db();
1070 add(&mut d, b"a", &[b"one", b"two"]);
1071 add(&mut d, b"b", &[b"two", b"three"]);
1072 assert_eq!(
1073 d.sunion([b"a".as_slice(), b"b"].into_iter(), 0, |_| {}),
1074 Ok(3)
1075 );
1076
1077 let many: Vec<Vec<u8>> = (0..500).map(|i| format!("m{i}").into_bytes()).collect();
1078 let refs: Vec<&[u8]> = many.iter().map(Vec::as_slice).collect();
1079 add(&mut d, b"c", &refs);
1080 let mut seen = Vec::new();
1081 assert_eq!(
1082 d.sunion([b"a".as_slice(), b"c"].into_iter(), 0, |m: &[u8]| seen
1083 .push(m.to_vec())),
1084 Ok(502)
1085 );
1086 seen.sort();
1087 seen.dedup();
1088 assert_eq!(seen.len(), 502, "every member came back once");
1089
1090 assert_eq!(
1093 d.sunion([b"a".as_slice(), b"b"].into_iter(), 0, |_| {}),
1094 Ok(3)
1095 );
1096 }
1097
1098 #[test]
1099 fn adding_to_a_key_that_is_not_there_makes_it() {
1100 let mut d = db();
1101 assert_eq!(add(&mut d, b"s", &[b"a", b"b", b"c"]), 3);
1102 assert_eq!(d.scard(b"s").expect("a set"), 3);
1103 assert_eq!(d.kind_of(b"s"), Some(Kind::Set));
1104 assert_eq!(members(&mut d, b"s"), ["a", "b", "c"]);
1105 assert_eq!(d.len(), 1, "one key, whatever the set holds");
1106 }
1107
1108 #[test]
1109 fn adding_answers_how_many_were_new_and_not_how_many_arrived() {
1110 let mut d = db();
1111 assert_eq!(add(&mut d, b"s", &[b"a", b"b"]), 2);
1112 assert_eq!(add(&mut d, b"s", &[b"b", b"c"]), 1);
1113 assert_eq!(
1114 add(&mut d, b"s", &[b"x", b"x", b"x"]),
1115 1,
1116 "the same member three times in one call is one member"
1117 );
1118 assert_eq!(d.scard(b"s").expect("a set"), 4);
1119 }
1120
1121 #[test]
1122 fn everything_answers_for_a_key_that_is_not_there() {
1123 let mut d = db();
1124 assert_eq!(d.scard(b"nope").expect("missing is fine"), 0);
1125 assert!(!d.sismember(b"nope", b"a").expect("missing is fine"));
1126 assert!(d.smembers(b"nope").expect("missing is fine").is_none());
1127 assert_eq!(
1128 d.srem(b"nope", [b"a".as_slice()].into_iter()).expect("ok"),
1129 0
1130 );
1131 assert_eq!(
1132 d.smismember(b"nope", [b"a".as_slice(), b"b"].into_iter())
1133 .expect("ok"),
1134 [false, false]
1135 );
1136 assert_eq!(d.len(), 0, "and none of that created anything");
1137 }
1138
1139 #[test]
1140 fn membership_answers_for_members_and_strangers() {
1141 let mut d = db();
1142 add(&mut d, b"s", &[b"a", b"b"]);
1143 assert!(d.sismember(b"s", b"a").expect("a set"));
1144 assert!(!d.sismember(b"s", b"z").expect("a set"));
1145 assert_eq!(
1146 d.smismember(b"s", [b"a".as_slice(), b"z", b"b"].into_iter())
1147 .expect("a set"),
1148 [true, false, true]
1149 );
1150 }
1151
1152 #[test]
1153 fn removing_the_last_member_removes_the_key() {
1154 let mut d = db();
1156 add(&mut d, b"s", &[b"a", b"b"]);
1157 assert_eq!(d.srem(b"s", [b"a".as_slice()].into_iter()).expect("ok"), 1);
1158 assert!(d.exists(b"s"), "one member left");
1159
1160 assert_eq!(
1161 d.srem(b"s", [b"b".as_slice(), b"gone"].into_iter())
1162 .expect("ok"),
1163 1,
1164 "one of the two was there"
1165 );
1166 assert!(!d.exists(b"s"), "and now the key is gone with it");
1167 assert_eq!(d.kind_of(b"s"), None);
1168 assert_eq!(d.len(), 0);
1169 }
1170
1171 #[test]
1172 fn a_set_is_deleted_body_and_all() {
1173 let mut d = db();
1177 add(&mut d, b"s", &[b"a", b"b"]);
1178 assert_eq!(d.sets.len(), 1);
1179
1180 assert!(d.del(b"s"));
1181 assert_eq!(d.sets.len(), 0, "the body went with the key");
1182 assert_eq!(d.bodies, 0);
1183
1184 add(&mut d, b"t", &[b"x"]);
1186 assert_eq!(d.sets.len(), 1);
1187 }
1188
1189 #[test]
1190 fn writing_a_string_over_a_set_takes_the_body_with_it() {
1191 let mut d = db();
1194 add(&mut d, b"k", &[b"a", b"b"]);
1195 assert_eq!(d.sets.len(), 1);
1196
1197 d.set_plain(b"k", b"now a string").expect("room");
1198 assert_eq!(d.sets.len(), 0, "the set went when it was written over");
1199 assert_eq!(d.bodies, 0);
1200 assert_eq!(d.kind_of(b"k"), Some(Kind::String));
1201 assert_eq!(
1202 d.get(b"k").expect("a string").map(|v| v.to_vec()),
1203 Some(b"now a string".to_vec())
1204 );
1205 }
1206
1207 #[test]
1208 fn a_set_that_expires_takes_its_body_with_it() {
1209 let mut d = db();
1210 add(&mut d, b"s", &[b"a"]);
1211 assert!(d.set_expiry(b"s", Some(1_100)));
1212 assert_eq!(d.expire_at(b"s"), Some(1_100));
1213 assert_eq!(d.sets.len(), 1);
1214 assert_eq!(d.scard(b"s").expect("a set"), 1, "still alive at 1000");
1215
1216 d.clock().advance(100);
1217 assert_eq!(d.scard(b"s").expect("gone is not an error"), 0);
1218 assert_eq!(d.sets.len(), 0, "reaping freed the body");
1219 assert_eq!(d.bodies, 0);
1220 assert_eq!(d.expired_keys(), 1);
1221 }
1222
1223 #[test]
1224 fn flushing_takes_every_body_with_it() {
1225 let mut d = db();
1226 for i in 0..10 {
1227 add(&mut d, format!("s{i}").as_bytes(), &[b"a", b"b"]);
1228 }
1229 assert_eq!(d.sets.len(), 10);
1230
1231 d.clear();
1232 assert_eq!(d.sets.len(), 0);
1233 assert_eq!(d.bodies, 0);
1234 assert_eq!(d.len(), 0);
1235 }
1236
1237 #[test]
1238 fn a_set_command_at_a_string_is_wrongtype() {
1239 let mut d = db();
1240 d.set_plain(b"k", b"v").expect("room");
1241
1242 let err = d.sadd(b"k", [b"a".as_slice()].into_iter()).expect_err("no");
1243 assert_eq!(err.code(), Code::WrongType);
1244 assert_eq!(
1245 err.message(),
1246 "Operation against a key holding the wrong kind of value"
1247 );
1248 assert!(d.scard(b"k").is_err());
1249 assert!(d.sismember(b"k", b"a").is_err());
1250 assert!(d.smembers(b"k").is_err());
1251 assert!(d.srem(b"k", [b"a".as_slice()].into_iter()).is_err());
1252 assert!(d.smismember(b"k", [b"a".as_slice()].into_iter()).is_err());
1253 assert_eq!(
1254 d.get(b"k").expect("still a string").map(|v| v.to_vec()),
1255 Some(b"v".to_vec()),
1256 "and none of that damaged it"
1257 );
1258 }
1259
1260 #[test]
1261 fn a_string_command_at_a_set_is_wrongtype() {
1262 let mut d = db();
1263 add(&mut d, b"s", &[b"a"]);
1264
1265 assert_eq!(d.get(b"s").expect_err("no").code(), Code::WrongType);
1266 assert!(d.strlen(b"s").is_err());
1267 assert!(d.getrange(b"s", 0, -1).is_err());
1268 assert!(d.getdel(b"s").is_err());
1269 assert!(d.incr(b"s").is_err());
1270 assert!(d.append(b"s", b"x").is_err());
1271 assert_eq!(d.scard(b"s").expect("a set"), 1, "and it is still a set");
1272 }
1273
1274 #[test]
1275 fn the_commands_that_do_not_care_still_do_not_care() {
1276 let mut d = db();
1279 add(&mut d, b"s", &[b"a"]);
1280
1281 assert!(d.exists(b"s"));
1282 assert_eq!(d.kind_of(b"s"), Some(Kind::Set));
1283 assert_eq!(d.encoding_name(b"s"), Some("listpack"));
1284 assert!(d.set_expiry(b"s", Some(6_000)));
1285 assert_eq!(d.expire_at(b"s"), Some(6_000));
1286 assert!(d.set_expiry(b"s", None), "and PERSIST takes it off again");
1287 assert_eq!(d.expire_at(b"s"), None);
1288 assert_eq!(d.scard(b"s").expect("a set"), 1, "through all of that");
1289 assert!(d.del(b"s"));
1290 }
1291
1292 #[test]
1293 fn mget_says_nil_for_a_set_rather_than_failing() {
1294 let mut d = db();
1298 d.set_plain(b"a", b"1").expect("room");
1299 add(&mut d, b"s", &[b"x"]);
1300 d.set_plain(b"z", b"2").expect("room");
1301
1302 let got: Vec<Option<Vec<u8>>> = d
1303 .mget(&[b"a", b"s", b"z", b"nope"])
1304 .into_iter()
1305 .map(|v| v.map(|s| s.to_vec()))
1306 .collect();
1307 assert_eq!(got, [Some(b"1".to_vec()), None, Some(b"2".to_vec()), None]);
1308 }
1309
1310 #[test]
1311 fn the_representation_follows_the_members_through_the_keyspace() {
1312 let mut d = db();
1316 add(&mut d, b"s", &[b"1", b"2", b"3"]);
1317 assert_eq!(d.set_encoding(b"s"), Some(Encoding::Intset));
1318
1319 add(&mut d, b"s", &[b"hello"]);
1320 assert_eq!(d.set_encoding(b"s"), Some(Encoding::Listpack));
1321 assert_eq!(members(&mut d, b"s"), ["1", "2", "3", "hello"]);
1322
1323 let long: Vec<u8> = vec![b'z'; 100];
1324 add(&mut d, b"s", &[&long]);
1325 assert_eq!(d.set_encoding(b"s"), Some(Encoding::Hashtable));
1326 assert_eq!(d.scard(b"s").expect("a set"), 5);
1327 assert!(d.sismember(b"s", b"1").expect("a set"), "nothing was lost");
1328 assert!(d.sismember(b"s", &long).expect("a set"));
1329 }
1330
1331 #[test]
1332 fn a_thousand_members_at_once_builds_a_table_without_converting() {
1333 let mut d = db();
1334 let owned: Vec<Vec<u8>> = (0..1000).map(|i| format!("m{i}").into_bytes()).collect();
1335 let refs: Vec<&[u8]> = owned.iter().map(Vec::as_slice).collect();
1336 assert_eq!(d.sadd(b"s", refs.iter().copied()).expect("a set"), 1000);
1337 assert_eq!(d.set_encoding(b"s"), Some(Encoding::Hashtable));
1338 assert_eq!(d.scard(b"s").expect("a set"), 1000);
1339 }
1340
1341 fn many(d: &mut Keyspace, key: &[u8], n: usize) {
1343 let owned: Vec<Vec<u8>> = (0..n).map(|i| format!("m{i}").into_bytes()).collect();
1344 let refs: Vec<&[u8]> = owned.iter().map(Vec::as_slice).collect();
1345 d.sadd(key, refs.iter().copied()).expect("a set");
1346 }
1347
1348 fn fill(d: &mut Keyspace, key: &[u8], n: usize, ints: bool) {
1351 let owned: Vec<Vec<u8>> = (0..n)
1352 .map(|i| {
1353 if ints {
1354 i.to_string().into_bytes()
1355 } else {
1356 format!("m{i}").into_bytes()
1357 }
1358 })
1359 .collect();
1360 let refs: Vec<&[u8]> = owned.iter().map(Vec::as_slice).collect();
1361 d.sadd(key, refs.iter().copied()).expect("a set");
1362 }
1363
1364 fn drawn(d: &mut Keyspace, key: &[u8], count: i64) -> Vec<String> {
1365 let mut out = Vec::new();
1366 d.srandmember_n(key, count, |m| {
1367 out.push(String::from_utf8(m.to_vec()).expect("utf8 in these tests"));
1368 })
1369 .expect("a set");
1370 out
1371 }
1372
1373 #[test]
1374 fn popping_takes_a_member_out_and_the_key_with_the_last_one() {
1375 let mut d = db();
1376 add(&mut d, b"s", &[b"a", b"b"]);
1377 let first = d.spop(b"s").expect("a set").expect("two members");
1378 assert_eq!(d.scard(b"s").expect("a set"), 1);
1379
1380 let second = d.spop(b"s").expect("a set").expect("one member");
1381 assert_ne!(first, second, "the same member came back twice");
1382 assert!(!d.exists(b"s"), "the last member took the key");
1383 assert_eq!(d.sets.len(), 0, "and the body");
1384 assert_eq!(d.spop(b"s").expect("gone is not an error"), None);
1385 }
1386
1387 #[test]
1388 fn popping_a_count_empties_a_set_without_repeating_itself() {
1389 for n in [4usize, 100, 300] {
1393 let mut d = db();
1394 many(&mut d, b"s", n);
1395 let got = d.spop_n(b"s", n + 10).expect("a set");
1396 assert_eq!(got.len(), n, "asked for more than there was");
1397 let mut sorted = got.clone();
1398 sorted.sort();
1399 sorted.dedup();
1400 assert_eq!(sorted.len(), n, "a member came back twice");
1401 assert!(!d.exists(b"s"));
1402 assert_eq!(d.sets.len(), 0);
1403 }
1404 }
1405
1406 #[test]
1407 fn popping_part_of_a_set_leaves_the_rest_of_it() {
1408 let mut d = db();
1409 many(&mut d, b"s", 10);
1410 let got = d.spop_n(b"s", 4).expect("a set");
1411 assert_eq!(got.len(), 4);
1412 assert_eq!(d.scard(b"s").expect("a set"), 6);
1413 for m in &got {
1414 assert!(!d.sismember(b"s", m).expect("a set"), "still there");
1415 }
1416 assert_eq!(
1417 d.spop_n(b"s", 0).expect("a set").len(),
1418 0,
1419 "and zero is none"
1420 );
1421 assert_eq!(d.scard(b"s").expect("a set"), 6);
1422 }
1423
1424 #[test]
1425 fn the_borrowing_draw_pops_the_same_set_the_copying_one_does() {
1426 for n in [4usize, 100, 300] {
1430 let mut a = db();
1431 a.seed(20_260_829);
1432 many(&mut a, b"s", n);
1433 let copied = a.spop_n(b"s", n).expect("a set");
1434
1435 let mut b = db();
1436 b.seed(20_260_829);
1437 many(&mut b, b"s", n);
1438 let mut borrowed = Vec::new();
1439 b.spop_into(b"s", n, |m| borrowed.push(m.to_vec()))
1440 .expect("a set");
1441
1442 assert_eq!(copied, borrowed, "{n} members drew differently");
1443 assert!(!b.exists(b"s"), "the last member took the key");
1444 assert_eq!(b.sets.len(), 0, "and the body");
1445 }
1446 }
1447
1448 #[test]
1449 fn the_borrowing_draw_allocates_nothing() {
1450 for n in [4usize, 100, 300] {
1456 for ints in [false, true] {
1457 let mut d = db();
1458 fill(&mut d, b"s", n, ints);
1459 let (drawn, allocs) = crate::tally::counted(|| {
1460 let mut bytes = 0;
1461 let mut count = 0;
1462 d.spop_into(b"s", n, |m| {
1463 bytes += m.byte_len();
1466 count += 1;
1467 })
1468 .expect("a set");
1469 (bytes, count)
1470 });
1471 assert_eq!(drawn.1, n, "{n} members, ints {ints}");
1472 assert!(drawn.0 > 0, "the members came back empty");
1473 assert_eq!(
1474 allocs, 0,
1475 "{n} members, ints {ints}: {allocs} allocations on the way out"
1476 );
1477 }
1478 }
1479 }
1480
1481 #[test]
1492 fn a_small_set_operation_stops_paying_per_key() {
1493 for (ints, want) in [(true, 0), (false, 6)] {
1494 let mut d = db();
1495 fill(&mut d, b"a", 8, ints);
1496 fill(&mut d, b"b", 8, ints);
1497 fill(&mut d, b"c", 8, ints);
1498 let keys: [&[u8]; 3] = [b"a", b"b", b"c"];
1499
1500 let (found, allocs) = crate::tally::counted(|| {
1501 let mut n = 0;
1502 d.sinter(keys.iter().copied(), 0, |_| n += 1).expect("sets");
1503 d.sunion(keys.iter().copied(), 0, |_| n += 1).expect("sets");
1504 d.sdiff(keys.iter().copied(), 0, |_| n += 1).expect("sets");
1505 n
1506 });
1507 assert!(found > 0, "ints {ints}: the operations found nothing");
1508 assert_eq!(
1509 allocs, want,
1510 "ints {ints}: {allocs} allocations for three ops, wanted {want}"
1511 );
1512 }
1513 }
1514
1515 #[test]
1518 fn a_wide_set_operation_still_answers() {
1519 let wide = crate::setops::INLINE_KEYS + 3;
1520 let mut d = db();
1521 let names: Vec<Vec<u8>> = (0..wide).map(|i| format!("k{i}").into_bytes()).collect();
1522 for name in &names {
1523 fill(&mut d, name, 8, true);
1524 }
1525 let keys = || names.iter().map(|k| k.as_slice());
1526 let mut inter = 0;
1527 d.sinter(keys(), 0, |_| inter += 1).expect("sets");
1528 assert_eq!(inter, 8);
1530 let mut union = 0;
1531 d.sunion(keys(), 0, |_| union += 1).expect("sets");
1532 assert_eq!(union, 8);
1533 }
1534
1535 #[test]
1536 fn the_copying_draw_allocates_a_member_at_a_time() {
1537 let mut d = db();
1541 many(&mut d, b"s", 100);
1542 let (got, allocs) = crate::tally::counted(|| d.spop_n(b"s", 100).expect("a set"));
1543 assert_eq!(got.len(), 100);
1544 assert!(allocs >= 100, "only {allocs} allocations for a hundred");
1545 }
1546
1547 #[test]
1548 fn a_pinned_seed_draws_the_same_members_twice() {
1549 let mut runs = Vec::new();
1553 for _ in 0..2 {
1554 let mut d = db();
1555 d.seed(20_260_828);
1556 many(&mut d, b"s", 50);
1557 runs.push(d.spop_n(b"s", 10).expect("a set"));
1558 }
1559 assert_eq!(runs[0], runs[1]);
1560 }
1561
1562 #[test]
1563 fn a_single_draw_reaches_every_member_and_removes_none() {
1564 let mut d = db();
1565 d.seed(7);
1566 add(&mut d, b"s", &[b"a", b"b", b"c"]);
1567 let mut seen = std::collections::HashSet::new();
1568 for _ in 0..200 {
1569 let got = d
1570 .srandmember(b"s", |m| m.map(|m| m.to_vec()))
1571 .expect("a set")
1572 .expect("a member");
1573 seen.insert(got);
1574 }
1575 assert_eq!(seen.len(), 3, "a draw that never reaches a member");
1576 assert_eq!(d.scard(b"s").expect("a set"), 3, "and nothing was taken");
1577
1578 assert!(
1579 d.srandmember(b"nope", |m| m.map(|m| m.to_vec()))
1580 .expect("missing is fine")
1581 .is_none()
1582 );
1583 }
1584
1585 #[test]
1586 fn a_negative_count_repeats_itself_and_a_positive_one_does_not() {
1587 let mut d = db();
1588 d.seed(11);
1589 add(&mut d, b"s", &[b"a", b"b", b"c"]);
1590
1591 let with_repeats = drawn(&mut d, b"s", -20);
1592 assert_eq!(with_repeats.len(), 20, "more members than the set holds");
1593
1594 let mut distinct = drawn(&mut d, b"s", 2);
1595 distinct.sort();
1596 distinct.dedup();
1597 assert_eq!(distinct.len(), 2);
1598 }
1599
1600 #[test]
1601 fn asking_for_more_than_the_set_holds_answers_all_of_it_once() {
1602 let mut d = db();
1603 d.seed(3);
1604 add(&mut d, b"s", &[b"a", b"b", b"c"]);
1605 let mut got = drawn(&mut d, b"s", 99);
1606 got.sort();
1607 assert_eq!(got, ["a", "b", "c"]);
1608 assert_eq!(drawn(&mut d, b"s", 0).len(), 0);
1609 assert_eq!(drawn(&mut d, b"nope", 5).len(), 0);
1610 assert_eq!(drawn(&mut d, b"nope", -5).len(), 0);
1611 }
1612
1613 #[test]
1614 fn both_ways_of_drawing_distinct_members_are_distinct_and_uniform() {
1615 let mut d = db();
1619 d.seed(99);
1620 many(&mut d, b"s", 1000);
1621
1622 for count in [2, 100, 400, 900] {
1623 let got = drawn(&mut d, b"s", count);
1624 let mut sorted = got.clone();
1625 sorted.sort();
1626 sorted.dedup();
1627 assert_eq!(
1628 sorted.len(),
1629 got.len(),
1630 "a draw of {count} repeated a member"
1631 );
1632 assert_eq!(got.len(), count as usize);
1633 }
1634
1635 let mut seen = std::collections::HashSet::new();
1638 for _ in 0..40 {
1639 seen.extend(drawn(&mut d, b"s", 900));
1640 seen.extend(drawn(&mut d, b"s", 2));
1641 }
1642 assert_eq!(seen.len(), 1000, "some member is never drawn");
1643 assert_eq!(d.scard(b"s").expect("a set"), 1000, "and none were taken");
1644 }
1645
1646 #[test]
1647 fn a_scan_walks_a_set_of_any_size_exactly_once() {
1648 for n in [3usize, 100, 500] {
1649 let mut d = db();
1650 many(&mut d, b"s", n);
1651 let mut seen = Vec::new();
1652 let mut c = Cursor::START;
1653 let mut turns = 0;
1654 loop {
1655 c = d
1656 .sscan(b"s", c, 10, |m| seen.push(m.to_vec()))
1657 .expect("a set");
1658 turns += 1;
1659 assert!(turns < 200, "the scan did not finish for {n} members");
1660 if c.is_end() {
1661 break;
1662 }
1663 }
1664 seen.sort();
1665 seen.dedup();
1666 assert_eq!(seen.len(), n, "a scan of {n} members missed one");
1667 }
1668 }
1669
1670 #[test]
1671 fn a_scan_of_a_key_that_is_not_there_is_a_finished_scan() {
1672 let mut d = db();
1673 let mut hit = 0;
1674 let c = d
1675 .sscan(b"nope", Cursor::START, 10, |_| hit += 1)
1676 .expect("ok");
1677 assert!(c.is_end());
1678 assert_eq!(hit, 0);
1679 }
1680
1681 #[test]
1682 fn a_scan_returns_everything_that_was_there_the_whole_time() {
1683 let mut d = db();
1688 many(&mut d, b"s", 500);
1689 let mut seen = Vec::new();
1690 let mut c = Cursor::START;
1691 let mut turns = 0;
1692 loop {
1693 c = d
1694 .sscan(b"s", c, 10, |m| seen.push(m.to_vec()))
1695 .expect("a set");
1696 let victim = format!("m{}", 400 + turns).into_bytes();
1699 d.srem(b"s", [victim.as_slice()].into_iter())
1700 .expect("a set");
1701 turns += 1;
1702 if c.is_end() {
1703 break;
1704 }
1705 }
1706 seen.sort();
1707 seen.dedup();
1708 for i in 0..400 {
1709 let m = format!("m{i}").into_bytes();
1710 assert!(seen.binary_search(&m).is_ok(), "m{i} was never returned");
1711 }
1712 }
1713
1714 #[test]
1715 fn moving_a_member_takes_it_off_one_set_and_puts_it_on_another() {
1716 let mut d = db();
1717 add(&mut d, b"a", &[b"x", b"y"]);
1718 add(&mut d, b"b", &[b"z"]);
1719
1720 assert!(d.smove(b"a", b"b", b"x").expect("two sets"));
1721 assert_eq!(members(&mut d, b"a"), ["y"]);
1722 assert_eq!(members(&mut d, b"b"), ["x", "z"]);
1723
1724 assert!(
1725 !d.smove(b"a", b"b", b"gone").expect("two sets"),
1726 "a member that is not in the source does not move"
1727 );
1728 assert!(
1729 d.smove(b"a", b"b", b"y").expect("two sets"),
1730 "and the last one still moves"
1731 );
1732 assert!(!d.exists(b"a"), "the source went with its last member");
1733 assert_eq!(d.sets.len(), 1, "and so did its body");
1734 assert_eq!(members(&mut d, b"b"), ["x", "y", "z"]);
1735 }
1736
1737 #[test]
1738 fn moving_onto_a_destination_that_is_not_there_makes_it() {
1739 let mut d = db();
1740 add(&mut d, b"a", &[b"x", b"y"]);
1741 assert!(d.smove(b"a", b"b", b"x").expect("a set"));
1742 assert_eq!(d.kind_of(b"b"), Some(Kind::Set));
1743 assert_eq!(members(&mut d, b"b"), ["x"]);
1744 assert_eq!(d.sets.len(), 2);
1745 }
1746
1747 #[test]
1748 fn moving_a_member_onto_its_own_set_changes_nothing() {
1749 let mut d = db();
1750 add(&mut d, b"a", &[b"x", b"y"]);
1751 assert!(d.smove(b"a", b"a", b"x").expect("a set"), "it is there");
1752 assert!(!d.smove(b"a", b"a", b"z").expect("a set"), "it is not");
1753 assert_eq!(members(&mut d, b"a"), ["x", "y"]);
1754 }
1755
1756 #[test]
1757 fn moving_checks_the_types_in_the_order_redis_checks_them() {
1758 let mut d = db();
1759 d.set_plain(b"str", b"v").expect("room");
1760 add(&mut d, b"s", &[b"x"]);
1761
1762 assert!(
1763 !d.smove(b"nope", b"str", b"x").expect("no source, no error"),
1764 "a missing source answers zero without looking at the destination"
1765 );
1766 assert_eq!(
1767 d.smove(b"str", b"s", b"x").expect_err("no").code(),
1768 Code::WrongType
1769 );
1770 assert_eq!(
1771 d.smove(b"s", b"str", b"x").expect_err("no").code(),
1772 Code::WrongType
1773 );
1774 assert_eq!(
1775 members(&mut d, b"s"),
1776 ["x"],
1777 "and the failed move left the source alone"
1778 );
1779 }
1780
1781 #[test]
1782 fn the_new_commands_answer_wrongtype_at_a_string() {
1783 let mut d = db();
1784 d.set_plain(b"k", b"v").expect("room");
1785 assert!(d.spop(b"k").is_err());
1786 assert!(d.spop_n(b"k", 2).is_err());
1787 assert!(d.srandmember(b"k", |m| m.is_some()).is_err());
1788 assert!(d.srandmember_n(b"k", 2, |_| ()).is_err());
1789 assert!(d.sscan(b"k", Cursor::START, 10, |_| ()).is_err());
1790 assert_eq!(
1791 d.get(b"k").expect("still a string").map(|v| v.to_vec()),
1792 Some(b"v".to_vec())
1793 );
1794 }
1795
1796 fn algebra(d: &mut Keyspace, op: &str, keys: &[&[u8]]) -> Vec<String> {
1799 let mut got = Vec::new();
1800 let mut take = |m: &[u8]| got.push(String::from_utf8_lossy(m).into_owned());
1801 let n = match op {
1802 "inter" => d.sinter(keys.iter().copied(), 0, &mut take),
1803 "union" => d.sunion(keys.iter().copied(), 0, &mut take),
1804 "diff" => d.sdiff(keys.iter().copied(), 0, &mut take),
1805 other => unreachable!("{other}"),
1806 }
1807 .expect("sets");
1808 assert_eq!(n, got.len(), "the count and the members disagree");
1809 got.sort();
1810 got
1811 }
1812
1813 #[test]
1814 fn the_algebra_answers_what_the_sets_share_and_do_not() {
1815 let mut d = db();
1816 add(&mut d, b"a", &[b"1", b"2", b"3"]);
1817 add(&mut d, b"b", &[b"2", b"3", b"4"]);
1818 add(&mut d, b"c", &[b"3", b"4", b"5"]);
1819
1820 assert_eq!(algebra(&mut d, "inter", &[b"a", b"b", b"c"]), ["3"]);
1821 assert_eq!(
1822 algebra(&mut d, "union", &[b"a", b"b", b"c"]),
1823 ["1", "2", "3", "4", "5"]
1824 );
1825 assert_eq!(algebra(&mut d, "diff", &[b"a", b"b"]), ["1"]);
1826 assert_eq!(
1827 algebra(&mut d, "diff", &[b"a"]),
1828 ["1", "2", "3"],
1829 "one set is that set"
1830 );
1831 assert_eq!(
1832 d.sintercard([b"a".as_slice(), b"b"].into_iter(), 0)
1833 .expect("sets"),
1834 2
1835 );
1836 assert_eq!(
1837 d.sintercard([b"a".as_slice(), b"b"].into_iter(), 1)
1838 .expect("sets"),
1839 1,
1840 "and a limit stops it early"
1841 );
1842 }
1843
1844 #[test]
1847 fn a_key_that_is_not_there_is_an_empty_set_everywhere() {
1848 let mut d = db();
1849 add(&mut d, b"a", &[b"1", b"2"]);
1850
1851 assert!(algebra(&mut d, "inter", &[b"a", b"nope"]).is_empty());
1852 assert!(algebra(&mut d, "inter", &[b"nope", b"a"]).is_empty());
1853 assert_eq!(algebra(&mut d, "union", &[b"a", b"nope"]), ["1", "2"]);
1854 assert_eq!(algebra(&mut d, "diff", &[b"a", b"nope"]), ["1", "2"]);
1855 assert!(
1856 algebra(&mut d, "diff", &[b"nope", b"a"]).is_empty(),
1857 "nothing minus anything is nothing"
1858 );
1859 assert!(algebra(&mut d, "union", &[b"nope"]).is_empty());
1860 assert_eq!(d.len(), 1, "and none of that made a key");
1861 }
1862
1863 #[test]
1864 fn a_store_form_writes_the_answer_and_says_how_big_it_is() {
1865 let mut d = db();
1866 add(&mut d, b"a", &[b"1", b"2", b"3"]);
1867 add(&mut d, b"b", &[b"2", b"3", b"4"]);
1868
1869 assert_eq!(
1870 d.sinterstore(b"d", [b"a".as_slice(), b"b"].into_iter())
1871 .expect("sets"),
1872 2
1873 );
1874 assert_eq!(members(&mut d, b"d"), ["2", "3"]);
1875 assert_eq!(
1876 d.sunionstore(b"d", [b"a".as_slice(), b"b"].into_iter())
1877 .expect("sets"),
1878 4
1879 );
1880 assert_eq!(members(&mut d, b"d"), ["1", "2", "3", "4"]);
1881 assert_eq!(
1882 d.sdiffstore(b"d", [b"a".as_slice(), b"b"].into_iter())
1883 .expect("sets"),
1884 1
1885 );
1886 assert_eq!(members(&mut d, b"d"), ["1"]);
1887 assert_eq!(d.encoding_name(b"d"), Some(Encoding::Intset.name()));
1890 }
1891
1892 #[test]
1895 fn a_store_form_of_nothing_deletes_the_destination() {
1896 let mut d = db();
1897 add(&mut d, b"a", &[b"1"]);
1898 add(&mut d, b"b", &[b"2"]);
1899 add(&mut d, b"d", &[b"old"]);
1900
1901 assert_eq!(
1902 d.sinterstore(b"d", [b"a".as_slice(), b"b"].into_iter())
1903 .expect("sets"),
1904 0
1905 );
1906 assert_eq!(d.kind_of(b"d"), None, "the destination went, not emptied");
1907 assert!(!d.exists(b"d"));
1908
1909 add(&mut d, b"d", &[b"old"]);
1912 assert_eq!(
1913 d.sdiffstore(b"d", [b"a".as_slice(), b"a"].into_iter())
1914 .expect("sets"),
1915 0
1916 );
1917 assert!(!d.exists(b"d"));
1918 add(&mut d, b"d", &[b"old"]);
1919 assert_eq!(
1920 d.sunionstore(b"d", [b"nope".as_slice()].into_iter())
1921 .expect("sets"),
1922 0
1923 );
1924 assert!(!d.exists(b"d"));
1925 }
1926
1927 #[test]
1930 fn a_store_form_can_write_over_one_of_its_own_sources() {
1931 let mut d = db();
1932 add(&mut d, b"a", &[b"1", b"2", b"3"]);
1933 add(&mut d, b"b", &[b"2", b"3", b"4"]);
1934
1935 assert_eq!(
1936 d.sinterstore(b"a", [b"a".as_slice(), b"b"].into_iter())
1937 .expect("sets"),
1938 2
1939 );
1940 assert_eq!(members(&mut d, b"a"), ["2", "3"]);
1941
1942 assert_eq!(
1944 d.sunionstore(b"a", [b"a".as_slice(), b"a"].into_iter())
1945 .expect("sets"),
1946 2
1947 );
1948 assert_eq!(members(&mut d, b"a"), ["2", "3"]);
1949 }
1950
1951 #[test]
1954 fn a_store_form_overwrites_whatever_the_destination_held() {
1955 let mut d = db();
1956 add(&mut d, b"a", &[b"1", b"2"]);
1957 d.set_plain(b"d", b"a string").expect("room");
1958 assert!(d.set_expiry(b"d", Some(9_999_999)));
1959
1960 assert_eq!(
1961 d.sunionstore(b"d", [b"a".as_slice()].into_iter())
1962 .expect("sets"),
1963 2
1964 );
1965 assert_eq!(d.kind_of(b"d"), Some(Kind::Set));
1966 assert_eq!(members(&mut d, b"d"), ["1", "2"]);
1967 assert_eq!(d.expire_at(b"d"), None, "and the deadline went with it");
1968 }
1969
1970 #[test]
1973 fn the_algebra_answers_wrongtype_before_it_writes_anything() {
1974 let mut d = db();
1975 add(&mut d, b"a", &[b"1"]);
1976 d.set_plain(b"str", b"v").expect("room");
1977 add(&mut d, b"d", &[b"old"]);
1978
1979 assert!(
1980 d.sinter([b"a".as_slice(), b"str"].into_iter(), 0, |_| ())
1981 .is_err()
1982 );
1983 assert!(
1984 d.sunion([b"str".as_slice()].into_iter(), 0, |_| ())
1985 .is_err()
1986 );
1987 assert!(
1988 d.sdiff([b"a".as_slice(), b"str"].into_iter(), 0, |_| ())
1989 .is_err()
1990 );
1991 assert!(
1992 d.sinterstore(b"d", [b"a".as_slice(), b"str"].into_iter())
1993 .is_err()
1994 );
1995 assert_eq!(members(&mut d, b"d"), ["old"], "and left it alone");
1996 }
1997
1998 #[test]
2001 fn the_algebra_works_across_the_representations() {
2002 let mut d = db();
2003 let big: Vec<Vec<u8>> = (0..600).map(|i| i.to_string().into_bytes()).collect();
2004 let refs: Vec<&[u8]> = big.iter().map(Vec::as_slice).collect();
2005 d.sadd(b"table", refs.iter().copied()).expect("a set");
2006 add(&mut d, b"ints", &[b"1", b"2", b"999"]);
2007 add(&mut d, b"packed", &[b"2", b"3", b"x"]);
2008 assert_eq!(d.encoding_name(b"table"), Some(Encoding::Hashtable.name()));
2009 assert_eq!(d.encoding_name(b"ints"), Some(Encoding::Intset.name()));
2010 assert_eq!(d.encoding_name(b"packed"), Some(Encoding::Listpack.name()));
2011
2012 assert_eq!(algebra(&mut d, "inter", &[b"ints", b"table"]), ["1", "2"]);
2016 assert_eq!(algebra(&mut d, "inter", &[b"packed", b"table"]), ["2", "3"]);
2017 assert_eq!(algebra(&mut d, "inter", &[b"ints", b"packed"]), ["2"]);
2018 assert_eq!(algebra(&mut d, "diff", &[b"ints", b"table"]), ["999"]);
2019 assert_eq!(
2020 algebra(&mut d, "union", &[b"ints", b"packed"]),
2021 ["1", "2", "3", "999", "x"]
2022 );
2023 }
2024
2025 #[test]
2026 fn a_set_is_counted_in_what_the_database_is_holding() {
2027 let mut d = db();
2028 let before = d.memory_bytes();
2029 let owned: Vec<Vec<u8>> = (0..500).map(|i| i.to_string().into_bytes()).collect();
2030 let refs: Vec<&[u8]> = owned.iter().map(Vec::as_slice).collect();
2031 d.sadd(b"s", refs.iter().copied()).expect("a set");
2032
2033 let after = d.memory_bytes();
2034 assert!(
2035 after > before + 500,
2036 "five hundred members have to show up somewhere: {before} then {after}"
2037 );
2038 d.del(b"s");
2039 assert!(d.memory_bytes() < after, "and go away again");
2040 }
2041
2042 #[test]
2049 fn a_deleted_key_does_not_answer_with_whatever_took_its_slot() {
2050 let mut d = db();
2051 add(&mut d, b"a", &[b"x", b"y", b"z"]);
2052 assert_eq!(d.scard(b"a").expect("a set"), 3);
2053
2054 d.del(b"a");
2055 add(&mut d, b"b", &[b"one"]);
2056
2057 assert_eq!(d.scard(b"a").expect("gone"), 0);
2058 assert!(!d.sismember(b"a", b"x").expect("gone"));
2059 assert_eq!(d.scard(b"b").expect("a set"), 1);
2060 }
2061
2062 #[test]
2066 fn a_key_that_comes_back_as_another_type_is_wrongtype() {
2067 let mut d = db();
2068 add(&mut d, b"k", &[b"x"]);
2069 assert_eq!(d.scard(b"k").expect("a set"), 1);
2070
2071 d.del(b"k");
2072 d.hset(b"k", [(&b"f"[..], &b"v"[..])].into_iter())
2073 .expect("a hash");
2074
2075 let err = d.scard(b"k").expect_err("a hash is not a set");
2076 assert_eq!(err.code(), Code::WrongType);
2077 }
2078
2079 #[test]
2083 fn a_key_with_a_deadline_still_expires_after_it_has_been_read() {
2084 let mut d = db();
2085 add(&mut d, b"k", &[b"x", b"y"]);
2086 assert_eq!(d.scard(b"k").expect("a set"), 2);
2087
2088 assert!(d.set_expiry(b"k", Some(1_500)));
2089 assert_eq!(d.scard(b"k").expect("still alive"), 2);
2090
2091 d.clock().advance(600);
2092 assert_eq!(d.scard(b"k").expect("past its deadline"), 0);
2093 assert!(!d.sismember(b"k", b"x").expect("past its deadline"));
2094 }
2095
2096 #[test]
2100 fn two_keys_in_a_row_do_not_answer_for_each_other() {
2101 let mut d = db();
2102 add(&mut d, b"a", &[b"1"]);
2103 add(&mut d, b"b", &[b"1", b"2", b"3"]);
2104 for _ in 0..8 {
2105 assert_eq!(d.scard(b"a").expect("a set"), 1);
2106 assert_eq!(d.scard(b"b").expect("a set"), 3);
2107 }
2108 }
2109
2110 #[test]
2113 fn a_flush_does_not_leave_the_last_key_behind() {
2114 let mut d = db();
2115 add(&mut d, b"k", &[b"x"]);
2116 assert_eq!(d.scard(b"k").expect("a set"), 1);
2117
2118 d.clear();
2119 assert_eq!(d.scard(b"k").expect("flushed"), 0);
2120 }
2121
2122 #[test]
2126 fn a_key_longer_than_the_memo_still_works() {
2127 let mut d = db();
2128 let long = vec![b'k'; 200];
2129 add(&mut d, &long, &[b"x", b"y"]);
2130 for _ in 0..4 {
2131 assert_eq!(d.scard(&long).expect("a set"), 2);
2132 }
2133 d.del(&long);
2134 assert_eq!(d.scard(&long).expect("gone"), 0);
2135 }
2136}