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