]> git.lizzy.rs Git - rust.git/blob - src/libcore/tests/ptr.rs
Incorporate a stray test
[rust.git] / src / libcore / tests / ptr.rs
1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use core::ptr::*;
12 use core::cell::RefCell;
13
14 #[test]
15 fn test() {
16     unsafe {
17         struct Pair {
18             fst: isize,
19             snd: isize
20         };
21         let mut p = Pair {fst: 10, snd: 20};
22         let pptr: *mut Pair = &mut p;
23         let iptr: *mut isize = pptr as *mut isize;
24         assert_eq!(*iptr, 10);
25         *iptr = 30;
26         assert_eq!(*iptr, 30);
27         assert_eq!(p.fst, 30);
28
29         *pptr = Pair {fst: 50, snd: 60};
30         assert_eq!(*iptr, 50);
31         assert_eq!(p.fst, 50);
32         assert_eq!(p.snd, 60);
33
34         let v0 = vec![32000u16, 32001u16, 32002u16];
35         let mut v1 = vec![0u16, 0u16, 0u16];
36
37         copy(v0.as_ptr().offset(1), v1.as_mut_ptr().offset(1), 1);
38         assert!((v1[0] == 0u16 &&
39                  v1[1] == 32001u16 &&
40                  v1[2] == 0u16));
41         copy(v0.as_ptr().offset(2), v1.as_mut_ptr(), 1);
42         assert!((v1[0] == 32002u16 &&
43                  v1[1] == 32001u16 &&
44                  v1[2] == 0u16));
45         copy(v0.as_ptr(), v1.as_mut_ptr().offset(2), 1);
46         assert!((v1[0] == 32002u16 &&
47                  v1[1] == 32001u16 &&
48                  v1[2] == 32000u16));
49     }
50 }
51
52 #[test]
53 fn test_is_null() {
54     let p: *const isize = null();
55     assert!(p.is_null());
56
57     let q = unsafe { p.offset(1) };
58     assert!(!q.is_null());
59
60     let mp: *mut isize = null_mut();
61     assert!(mp.is_null());
62
63     let mq = unsafe { mp.offset(1) };
64     assert!(!mq.is_null());
65
66     // Pointers to unsized types -- slices
67     let s: &mut [u8] = &mut [1, 2, 3];
68     let cs: *const [u8] = s;
69     assert!(!cs.is_null());
70
71     let ms: *mut [u8] = s;
72     assert!(!ms.is_null());
73
74     let cz: *const [u8] = &[];
75     assert!(!cz.is_null());
76
77     let mz: *mut [u8] = &mut [];
78     assert!(!mz.is_null());
79
80     let ncs: *const [u8] = null::<[u8; 3]>();
81     assert!(ncs.is_null());
82
83     let nms: *mut [u8] = null_mut::<[u8; 3]>();
84     assert!(nms.is_null());
85
86     // Pointers to unsized types -- trait objects
87     let ci: *const ToString = &3;
88     assert!(!ci.is_null());
89
90     let mi: *mut ToString = &mut 3;
91     assert!(!mi.is_null());
92
93     let nci: *const ToString = null::<isize>();
94     assert!(nci.is_null());
95
96     let nmi: *mut ToString = null_mut::<isize>();
97     assert!(nmi.is_null());
98 }
99
100 #[test]
101 fn test_as_ref() {
102     unsafe {
103         let p: *const isize = null();
104         assert_eq!(p.as_ref(), None);
105
106         let q: *const isize = &2;
107         assert_eq!(q.as_ref().unwrap(), &2);
108
109         let p: *mut isize = null_mut();
110         assert_eq!(p.as_ref(), None);
111
112         let q: *mut isize = &mut 2;
113         assert_eq!(q.as_ref().unwrap(), &2);
114
115         // Lifetime inference
116         let u = 2isize;
117         {
118             let p = &u as *const isize;
119             assert_eq!(p.as_ref().unwrap(), &2);
120         }
121
122         // Pointers to unsized types -- slices
123         let s: &mut [u8] = &mut [1, 2, 3];
124         let cs: *const [u8] = s;
125         assert_eq!(cs.as_ref(), Some(&*s));
126
127         let ms: *mut [u8] = s;
128         assert_eq!(ms.as_ref(), Some(&*s));
129
130         let cz: *const [u8] = &[];
131         assert_eq!(cz.as_ref(), Some(&[][..]));
132
133         let mz: *mut [u8] = &mut [];
134         assert_eq!(mz.as_ref(), Some(&[][..]));
135
136         let ncs: *const [u8] = null::<[u8; 3]>();
137         assert_eq!(ncs.as_ref(), None);
138
139         let nms: *mut [u8] = null_mut::<[u8; 3]>();
140         assert_eq!(nms.as_ref(), None);
141
142         // Pointers to unsized types -- trait objects
143         let ci: *const ToString = &3;
144         assert!(ci.as_ref().is_some());
145
146         let mi: *mut ToString = &mut 3;
147         assert!(mi.as_ref().is_some());
148
149         let nci: *const ToString = null::<isize>();
150         assert!(nci.as_ref().is_none());
151
152         let nmi: *mut ToString = null_mut::<isize>();
153         assert!(nmi.as_ref().is_none());
154     }
155 }
156
157 #[test]
158 fn test_as_mut() {
159     unsafe {
160         let p: *mut isize = null_mut();
161         assert!(p.as_mut() == None);
162
163         let q: *mut isize = &mut 2;
164         assert!(q.as_mut().unwrap() == &mut 2);
165
166         // Lifetime inference
167         let mut u = 2isize;
168         {
169             let p = &mut u as *mut isize;
170             assert!(p.as_mut().unwrap() == &mut 2);
171         }
172
173         // Pointers to unsized types -- slices
174         let s: &mut [u8] = &mut [1, 2, 3];
175         let ms: *mut [u8] = s;
176         assert_eq!(ms.as_mut(), Some(s));
177
178         let mz: *mut [u8] = &mut [];
179         assert_eq!(mz.as_mut(), Some(&mut [][..]));
180
181         let nms: *mut [u8] = null_mut::<[u8; 3]>();
182         assert_eq!(nms.as_mut(), None);
183
184         // Pointers to unsized types -- trait objects
185         let mi: *mut ToString = &mut 3;
186         assert!(mi.as_mut().is_some());
187
188         let nmi: *mut ToString = null_mut::<isize>();
189         assert!(nmi.as_mut().is_none());
190     }
191 }
192
193 #[test]
194 fn test_ptr_addition() {
195     unsafe {
196         let xs = vec![5; 16];
197         let mut ptr = xs.as_ptr();
198         let end = ptr.offset(16);
199
200         while ptr < end {
201             assert_eq!(*ptr, 5);
202             ptr = ptr.offset(1);
203         }
204
205         let mut xs_mut = xs;
206         let mut m_ptr = xs_mut.as_mut_ptr();
207         let m_end = m_ptr.offset(16);
208
209         while m_ptr < m_end {
210             *m_ptr += 5;
211             m_ptr = m_ptr.offset(1);
212         }
213
214         assert!(xs_mut == vec![10; 16]);
215     }
216 }
217
218 #[test]
219 fn test_ptr_subtraction() {
220     unsafe {
221         let xs = vec![0,1,2,3,4,5,6,7,8,9];
222         let mut idx = 9;
223         let ptr = xs.as_ptr();
224
225         while idx >= 0 {
226             assert_eq!(*(ptr.offset(idx as isize)), idx as isize);
227             idx = idx - 1;
228         }
229
230         let mut xs_mut = xs;
231         let m_start = xs_mut.as_mut_ptr();
232         let mut m_ptr = m_start.offset(9);
233
234         while m_ptr >= m_start {
235             *m_ptr += *m_ptr;
236             m_ptr = m_ptr.offset(-1);
237         }
238
239         assert_eq!(xs_mut, [0,2,4,6,8,10,12,14,16,18]);
240     }
241 }
242
243 #[test]
244 fn test_set_memory() {
245     let mut xs = [0u8; 20];
246     let ptr = xs.as_mut_ptr();
247     unsafe { write_bytes(ptr, 5u8, xs.len()); }
248     assert!(xs == [5u8; 20]);
249 }
250
251 #[test]
252 fn test_unsized_nonnull() {
253     let xs: &[i32] = &[1, 2, 3];
254     let ptr = unsafe { NonNull::new_unchecked(xs as *const [i32] as *mut [i32]) };
255     let ys = unsafe { ptr.as_ref() };
256     let zs: &[i32] = &[1, 2, 3];
257     assert!(ys == zs);
258 }
259
260 #[test]
261 #[allow(warnings)]
262 // Have a symbol for the test below. It doesn’t need to be an actual variadic function, match the
263 // ABI, or even point to an actual executable code, because the function itself is never invoked.
264 #[no_mangle]
265 pub fn test_variadic_fnptr() {
266     use core::hash::{Hash, SipHasher};
267     extern {
268         fn test_variadic_fnptr(_: u64, ...) -> f64;
269     }
270     let p: unsafe extern fn(u64, ...) -> f64 = test_variadic_fnptr;
271     let q = p.clone();
272     assert_eq!(p, q);
273     assert!(!(p < q));
274     let mut s = SipHasher::new();
275     assert_eq!(p.hash(&mut s), q.hash(&mut s));
276 }
277
278 #[test]
279 fn write_unaligned_drop() {
280     thread_local! {
281         static DROPS: RefCell<Vec<u32>> = RefCell::new(Vec::new());
282     }
283
284     struct Dropper(u32);
285
286     impl Drop for Dropper {
287         fn drop(&mut self) {
288             DROPS.with(|d| d.borrow_mut().push(self.0));
289         }
290     }
291
292     {
293         let c = Dropper(0);
294         let mut t = Dropper(1);
295         unsafe { write_unaligned(&mut t, c); }
296     }
297     DROPS.with(|d| assert_eq!(*d.borrow(), [0]));
298 }
299
300 #[test]
301 fn align_offset_zst() {
302     // For pointers of stride = 0, the pointer is already aligned or it cannot be aligned at
303     // all, because no amount of elements will align the pointer.
304     let mut p = 1;
305     while p < 1024 {
306         assert_eq!((p as *const ()).align_offset(p), 0);
307         if p != 1 {
308             assert_eq!(((p + 1) as *const ()).align_offset(p), !0);
309         }
310         p = (p + 1).next_power_of_two();
311     }
312 }
313
314 #[test]
315 fn align_offset_stride1() {
316     // For pointers of stride = 1, the pointer can always be aligned. The offset is equal to
317     // number of bytes.
318     let mut align = 1;
319     while align < 1024 {
320         for ptr in 1..2*align {
321             let expected = ptr % align;
322             let offset = if expected == 0 { 0 } else { align - expected };
323             assert_eq!((ptr as *const u8).align_offset(align), offset,
324             "ptr = {}, align = {}, size = 1", ptr, align);
325         }
326         align = (align + 1).next_power_of_two();
327     }
328 }
329
330 #[test]
331 fn align_offset_weird_strides() {
332     #[repr(packed)]
333     struct A3(u16, u8);
334     struct A4(u32);
335     #[repr(packed)]
336     struct A5(u32, u8);
337     #[repr(packed)]
338     struct A6(u32, u16);
339     #[repr(packed)]
340     struct A7(u32, u16, u8);
341     #[repr(packed)]
342     struct A8(u32, u32);
343     #[repr(packed)]
344     struct A9(u32, u32, u8);
345     #[repr(packed)]
346     struct A10(u32, u32, u16);
347
348     unsafe fn test_weird_stride<T>(ptr: *const T, align: usize) -> bool {
349         let numptr = ptr as usize;
350         let mut expected = usize::max_value();
351         // Naive but definitely correct way to find the *first* aligned element of stride::<T>.
352         for el in 0..align {
353             if (numptr + el * ::std::mem::size_of::<T>()) % align == 0 {
354                 expected = el;
355                 break;
356             }
357         }
358         let got = ptr.align_offset(align);
359         if got != expected {
360             eprintln!("aligning {:p} (with stride of {}) to {}, expected {}, got {}", ptr,
361                       ::std::mem::size_of::<T>(), align, expected, got);
362             return true;
363         }
364         return false;
365     }
366
367     // For pointers of stride != 1, we verify the algorithm against the naivest possible
368     // implementation
369     let mut align = 1;
370     let mut x = false;
371     while align < 1024 {
372         for ptr in 1usize..4*align {
373             unsafe {
374                 x |= test_weird_stride::<A3>(ptr as *const A3, align);
375                 x |= test_weird_stride::<A4>(ptr as *const A4, align);
376                 x |= test_weird_stride::<A5>(ptr as *const A5, align);
377                 x |= test_weird_stride::<A6>(ptr as *const A6, align);
378                 x |= test_weird_stride::<A7>(ptr as *const A7, align);
379                 x |= test_weird_stride::<A8>(ptr as *const A8, align);
380                 x |= test_weird_stride::<A9>(ptr as *const A9, align);
381                 x |= test_weird_stride::<A10>(ptr as *const A10, align);
382             }
383         }
384         align = (align + 1).next_power_of_two();
385     }
386     assert!(!x);
387 }