]> git.lizzy.rs Git - rust.git/blob - library/core/tests/cell.rs
Merge commit '0cb0f7636851f9fcc57085cf80197a2ef6db098f' into clippyup
[rust.git] / library / core / tests / cell.rs
1 use core::cell::*;
2 use core::default::Default;
3 use std::mem::drop;
4
5 #[test]
6 fn smoketest_unsafe_cell() {
7     let mut x = UnsafeCell::new(10);
8     let ref_mut = &mut x;
9     unsafe {
10         // The asserts are repeated in order to ensure that `get()`
11         // is non-mutating.
12         assert_eq!(*ref_mut.get(), 10);
13         assert_eq!(*ref_mut.get(), 10);
14         *ref_mut.get_mut() += 5;
15         assert_eq!(*ref_mut.get(), 15);
16         assert_eq!(*ref_mut.get(), 15);
17         assert_eq!(x.into_inner(), 15);
18     }
19 }
20
21 #[test]
22 fn unsafe_cell_raw_get() {
23     let x = UnsafeCell::new(10);
24     let ptr = &x as *const UnsafeCell<i32>;
25     unsafe {
26         // The asserts are repeated in order to ensure that `raw_get()`
27         // is non-mutating.
28         assert_eq!(*UnsafeCell::raw_get(ptr), 10);
29         assert_eq!(*UnsafeCell::raw_get(ptr), 10);
30         *UnsafeCell::raw_get(ptr) += 5;
31         assert_eq!(*UnsafeCell::raw_get(ptr), 15);
32         assert_eq!(*UnsafeCell::raw_get(ptr), 15);
33         assert_eq!(x.into_inner(), 15);
34     }
35 }
36
37 #[test]
38 fn smoketest_cell() {
39     let x = Cell::new(10);
40     assert_eq!(x, Cell::new(10));
41     assert_eq!(x.get(), 10);
42     x.set(20);
43     assert_eq!(x, Cell::new(20));
44     assert_eq!(x.get(), 20);
45
46     let y = Cell::new((30, 40));
47     assert_eq!(y, Cell::new((30, 40)));
48     assert_eq!(y.get(), (30, 40));
49 }
50
51 #[test]
52 fn cell_update() {
53     let x = Cell::new(10);
54
55     assert_eq!(x.update(|x| x + 5), 15);
56     assert_eq!(x.get(), 15);
57
58     assert_eq!(x.update(|x| x / 3), 5);
59     assert_eq!(x.get(), 5);
60 }
61
62 #[test]
63 fn cell_has_sensible_show() {
64     let x = Cell::new("foo bar");
65     assert!(format!("{x:?}").contains(x.get()));
66
67     x.set("baz qux");
68     assert!(format!("{x:?}").contains(x.get()));
69 }
70
71 #[test]
72 fn ref_and_refmut_have_sensible_show() {
73     let refcell = RefCell::new("foo");
74
75     let refcell_refmut = refcell.borrow_mut();
76     assert_eq!(format!("{refcell_refmut}"), "foo"); // Display
77     assert!(format!("{refcell_refmut:?}").contains("foo")); // Debug
78     drop(refcell_refmut);
79
80     let refcell_ref = refcell.borrow();
81     assert_eq!(format!("{refcell_ref}"), "foo"); // Display
82     assert!(format!("{refcell_ref:?}").contains("foo")); // Debug
83     drop(refcell_ref);
84 }
85
86 #[test]
87 fn double_imm_borrow() {
88     let x = RefCell::new(0);
89     let _b1 = x.borrow();
90     x.borrow();
91 }
92
93 #[test]
94 fn no_mut_then_imm_borrow() {
95     let x = RefCell::new(0);
96     let _b1 = x.borrow_mut();
97     assert!(x.try_borrow().is_err());
98 }
99
100 #[test]
101 fn no_imm_then_borrow_mut() {
102     let x = RefCell::new(0);
103     let _b1 = x.borrow();
104     assert!(x.try_borrow_mut().is_err());
105 }
106
107 #[test]
108 fn no_double_borrow_mut() {
109     let x = RefCell::new(0);
110     assert!(x.try_borrow().is_ok());
111     let _b1 = x.borrow_mut();
112     assert!(x.try_borrow().is_err());
113 }
114
115 #[test]
116 fn imm_release_borrow_mut() {
117     let x = RefCell::new(0);
118     {
119         let _b1 = x.borrow();
120     }
121     x.borrow_mut();
122 }
123
124 #[test]
125 fn mut_release_borrow_mut() {
126     let x = RefCell::new(0);
127     {
128         let _b1 = x.borrow_mut();
129     }
130     x.borrow();
131 }
132
133 #[test]
134 fn double_borrow_single_release_no_borrow_mut() {
135     let x = RefCell::new(0);
136     let _b1 = x.borrow();
137     {
138         let _b2 = x.borrow();
139     }
140     assert!(x.try_borrow().is_ok());
141     assert!(x.try_borrow_mut().is_err());
142 }
143
144 #[test]
145 #[should_panic]
146 fn discard_doesnt_unborrow() {
147     let x = RefCell::new(0);
148     let _b = x.borrow();
149     let _ = _b;
150     let _b = x.borrow_mut();
151 }
152
153 #[test]
154 fn ref_clone_updates_flag() {
155     let x = RefCell::new(0);
156     {
157         let b1 = x.borrow();
158         assert!(x.try_borrow().is_ok());
159         assert!(x.try_borrow_mut().is_err());
160         {
161             let _b2 = Ref::clone(&b1);
162             assert!(x.try_borrow().is_ok());
163             assert!(x.try_borrow_mut().is_err());
164         }
165         assert!(x.try_borrow().is_ok());
166         assert!(x.try_borrow_mut().is_err());
167     }
168     assert!(x.try_borrow().is_ok());
169     assert!(x.try_borrow_mut().is_ok());
170 }
171
172 #[test]
173 fn ref_map_does_not_update_flag() {
174     let x = RefCell::new(Some(5));
175     {
176         let b1: Ref<'_, Option<u32>> = x.borrow();
177         assert!(x.try_borrow().is_ok());
178         assert!(x.try_borrow_mut().is_err());
179         {
180             let b2: Ref<'_, u32> = Ref::map(b1, |o| o.as_ref().unwrap());
181             assert_eq!(*b2, 5);
182             assert!(x.try_borrow().is_ok());
183             assert!(x.try_borrow_mut().is_err());
184         }
185         assert!(x.try_borrow().is_ok());
186         assert!(x.try_borrow_mut().is_ok());
187     }
188     assert!(x.try_borrow().is_ok());
189     assert!(x.try_borrow_mut().is_ok());
190 }
191
192 #[test]
193 fn ref_map_split_updates_flag() {
194     let x = RefCell::new([1, 2]);
195     {
196         let b1 = x.borrow();
197         assert!(x.try_borrow().is_ok());
198         assert!(x.try_borrow_mut().is_err());
199         {
200             let (_b2, _b3) = Ref::map_split(b1, |slc| slc.split_at(1));
201             assert!(x.try_borrow().is_ok());
202             assert!(x.try_borrow_mut().is_err());
203         }
204         assert!(x.try_borrow().is_ok());
205         assert!(x.try_borrow_mut().is_ok());
206     }
207     assert!(x.try_borrow().is_ok());
208     assert!(x.try_borrow_mut().is_ok());
209
210     {
211         let b1 = x.borrow_mut();
212         assert!(x.try_borrow().is_err());
213         assert!(x.try_borrow_mut().is_err());
214         {
215             let (_b2, _b3) = RefMut::map_split(b1, |slc| slc.split_at_mut(1));
216             assert!(x.try_borrow().is_err());
217             assert!(x.try_borrow_mut().is_err());
218             drop(_b2);
219             assert!(x.try_borrow().is_err());
220             assert!(x.try_borrow_mut().is_err());
221         }
222         assert!(x.try_borrow().is_ok());
223         assert!(x.try_borrow_mut().is_ok());
224     }
225     assert!(x.try_borrow().is_ok());
226     assert!(x.try_borrow_mut().is_ok());
227 }
228
229 #[test]
230 fn ref_map_split() {
231     let x = RefCell::new([1, 2]);
232     let (b1, b2) = Ref::map_split(x.borrow(), |slc| slc.split_at(1));
233     assert_eq!(*b1, [1]);
234     assert_eq!(*b2, [2]);
235 }
236
237 #[test]
238 fn ref_mut_map_split() {
239     let x = RefCell::new([1, 2]);
240     {
241         let (mut b1, mut b2) = RefMut::map_split(x.borrow_mut(), |slc| slc.split_at_mut(1));
242         assert_eq!(*b1, [1]);
243         assert_eq!(*b2, [2]);
244         b1[0] = 2;
245         b2[0] = 1;
246     }
247     assert_eq!(*x.borrow(), [2, 1]);
248 }
249
250 #[test]
251 fn ref_map_accessor() {
252     struct X(RefCell<(u32, char)>);
253     impl X {
254         fn accessor(&self) -> Ref<'_, u32> {
255             Ref::map(self.0.borrow(), |tuple| &tuple.0)
256         }
257     }
258     let x = X(RefCell::new((7, 'z')));
259     let d: Ref<'_, u32> = x.accessor();
260     assert_eq!(*d, 7);
261 }
262
263 #[test]
264 fn ref_mut_map_accessor() {
265     struct X(RefCell<(u32, char)>);
266     impl X {
267         fn accessor(&self) -> RefMut<'_, u32> {
268             RefMut::map(self.0.borrow_mut(), |tuple| &mut tuple.0)
269         }
270     }
271     let x = X(RefCell::new((7, 'z')));
272     {
273         let mut d: RefMut<'_, u32> = x.accessor();
274         assert_eq!(*d, 7);
275         *d += 1;
276     }
277     assert_eq!(*x.0.borrow(), (8, 'z'));
278 }
279
280 #[test]
281 fn as_ptr() {
282     let c1: Cell<usize> = Cell::new(0);
283     c1.set(1);
284     assert_eq!(1, unsafe { *c1.as_ptr() });
285
286     let c2: Cell<usize> = Cell::new(0);
287     unsafe {
288         *c2.as_ptr() = 1;
289     }
290     assert_eq!(1, c2.get());
291
292     let r1: RefCell<usize> = RefCell::new(0);
293     *r1.borrow_mut() = 1;
294     assert_eq!(1, unsafe { *r1.as_ptr() });
295
296     let r2: RefCell<usize> = RefCell::new(0);
297     unsafe {
298         *r2.as_ptr() = 1;
299     }
300     assert_eq!(1, *r2.borrow());
301 }
302
303 #[test]
304 fn cell_default() {
305     let cell: Cell<u32> = Default::default();
306     assert_eq!(0, cell.get());
307 }
308
309 #[test]
310 fn cell_set() {
311     let cell = Cell::new(10);
312     cell.set(20);
313     assert_eq!(20, cell.get());
314
315     let cell = Cell::new("Hello".to_owned());
316     cell.set("World".to_owned());
317     assert_eq!("World".to_owned(), cell.into_inner());
318 }
319
320 #[test]
321 fn cell_replace() {
322     let cell = Cell::new(10);
323     assert_eq!(10, cell.replace(20));
324     assert_eq!(20, cell.get());
325
326     let cell = Cell::new("Hello".to_owned());
327     assert_eq!("Hello".to_owned(), cell.replace("World".to_owned()));
328     assert_eq!("World".to_owned(), cell.into_inner());
329 }
330
331 #[test]
332 fn cell_into_inner() {
333     let cell = Cell::new(10);
334     assert_eq!(10, cell.into_inner());
335
336     let cell = Cell::new("Hello world".to_owned());
337     assert_eq!("Hello world".to_owned(), cell.into_inner());
338 }
339
340 #[test]
341 fn cell_exterior() {
342     #[derive(Copy, Clone)]
343     #[allow(dead_code)]
344     struct Point {
345         x: isize,
346         y: isize,
347         z: isize,
348     }
349
350     fn f(p: &Cell<Point>) {
351         assert_eq!(p.get().z, 12);
352         p.set(Point { x: 10, y: 11, z: 13 });
353         assert_eq!(p.get().z, 13);
354     }
355
356     let a = Point { x: 10, y: 11, z: 12 };
357     let b = &Cell::new(a);
358     assert_eq!(b.get().z, 12);
359     f(b);
360     assert_eq!(a.z, 12);
361     assert_eq!(b.get().z, 13);
362 }
363
364 #[test]
365 fn cell_does_not_clone() {
366     #[derive(Copy)]
367     #[allow(dead_code)]
368     struct Foo {
369         x: isize,
370     }
371
372     impl Clone for Foo {
373         fn clone(&self) -> Foo {
374             // Using Cell in any way should never cause clone() to be
375             // invoked -- after all, that would permit evil user code to
376             // abuse `Cell` and trigger crashes.
377
378             panic!();
379         }
380     }
381
382     let x = Cell::new(Foo { x: 22 });
383     let _y = x.get();
384     let _z = x.clone();
385 }
386
387 #[test]
388 fn refcell_default() {
389     let cell: RefCell<u64> = Default::default();
390     assert_eq!(0, *cell.borrow());
391 }
392
393 #[test]
394 fn unsafe_cell_unsized() {
395     let cell: &UnsafeCell<[i32]> = &UnsafeCell::new([1, 2, 3]);
396     {
397         let val: &mut [i32] = unsafe { &mut *cell.get() };
398         val[0] = 4;
399         val[2] = 5;
400     }
401     let comp: &mut [i32] = &mut [4, 2, 5];
402     assert_eq!(unsafe { &mut *cell.get() }, comp);
403 }
404
405 #[test]
406 fn refcell_unsized() {
407     let cell: &RefCell<[i32]> = &RefCell::new([1, 2, 3]);
408     {
409         let b = &mut *cell.borrow_mut();
410         b[0] = 4;
411         b[2] = 5;
412     }
413     let comp: &mut [i32] = &mut [4, 2, 5];
414     assert_eq!(&*cell.borrow(), comp);
415 }
416
417 #[test]
418 fn refcell_ref_coercion() {
419     let cell: RefCell<[i32; 3]> = RefCell::new([1, 2, 3]);
420     {
421         let mut cellref: RefMut<'_, [i32; 3]> = cell.borrow_mut();
422         cellref[0] = 4;
423         let mut coerced: RefMut<'_, [i32]> = cellref;
424         coerced[2] = 5;
425     }
426     {
427         let comp: &mut [i32] = &mut [4, 2, 5];
428         let cellref: Ref<'_, [i32; 3]> = cell.borrow();
429         assert_eq!(&*cellref, comp);
430         let coerced: Ref<'_, [i32]> = cellref;
431         assert_eq!(&*coerced, comp);
432     }
433 }
434
435 #[test]
436 #[should_panic]
437 fn refcell_swap_borrows() {
438     let x = RefCell::new(0);
439     let _b = x.borrow();
440     let y = RefCell::new(1);
441     x.swap(&y);
442 }
443
444 #[test]
445 #[should_panic]
446 fn refcell_replace_borrows() {
447     let x = RefCell::new(0);
448     let _b = x.borrow();
449     x.replace(1);
450 }
451
452 #[test]
453 fn refcell_format() {
454     let name = RefCell::new("rust");
455     let what = RefCell::new("rocks");
456     let msg = format!("{name} {}", &*what.borrow(), name = &*name.borrow());
457     assert_eq!(msg, "rust rocks".to_string());
458 }
459
460 #[allow(dead_code)]
461 fn const_cells() {
462     const UNSAFE_CELL: UnsafeCell<i32> = UnsafeCell::new(3);
463     const _: i32 = UNSAFE_CELL.into_inner();
464
465     const REF_CELL: RefCell<i32> = RefCell::new(3);
466     const _: i32 = REF_CELL.into_inner();
467
468     const CELL: Cell<i32> = Cell::new(3);
469     const _: i32 = CELL.into_inner();
470
471     const UNSAFE_CELL_FROM: UnsafeCell<i32> = UnsafeCell::from(3);
472     const _: i32 = UNSAFE_CELL.into_inner();
473
474     const REF_CELL_FROM: RefCell<i32> = RefCell::from(3);
475     const _: i32 = REF_CELL.into_inner();
476
477     const CELL_FROM: Cell<i32> = Cell::from(3);
478     const _: i32 = CELL.into_inner();
479 }