| 1 | #[macro_use ] |
| 2 | extern crate lazy_static; |
| 3 | use std::collections::HashMap; |
| 4 | |
| 5 | lazy_static! { |
| 6 | /// Documentation! |
| 7 | pub static ref NUMBER: u32 = times_two(3); |
| 8 | |
| 9 | static ref ARRAY_BOXES: [Box<u32>; 3] = [Box::new(1), Box::new(2), Box::new(3)]; |
| 10 | |
| 11 | /// More documentation! |
| 12 | #[allow (unused_variables)] |
| 13 | #[derive(Copy, Clone, Debug)] |
| 14 | pub static ref STRING: String = "hello" .to_string(); |
| 15 | |
| 16 | static ref HASHMAP: HashMap<u32, &'static str> = { |
| 17 | let mut m = HashMap::new(); |
| 18 | m.insert(0, "abc" ); |
| 19 | m.insert(1, "def" ); |
| 20 | m.insert(2, "ghi" ); |
| 21 | m |
| 22 | }; |
| 23 | |
| 24 | // This should not compile if the unsafe is removed. |
| 25 | static ref UNSAFE: u32 = unsafe { |
| 26 | std::mem::transmute::<i32, u32>(-1) |
| 27 | }; |
| 28 | } |
| 29 | |
| 30 | lazy_static! { |
| 31 | static ref S1: &'static str = "a" ; |
| 32 | static ref S2: &'static str = "b" ; |
| 33 | } |
| 34 | lazy_static! { |
| 35 | static ref S3: String = [*S1, *S2].join("" ); |
| 36 | } |
| 37 | |
| 38 | #[test] |
| 39 | fn s3() { |
| 40 | assert_eq!(&*S3, "ab" ); |
| 41 | } |
| 42 | |
| 43 | fn times_two(n: u32) -> u32 { |
| 44 | n * 2 |
| 45 | } |
| 46 | |
| 47 | #[test] |
| 48 | fn test_basic() { |
| 49 | assert_eq!(&**STRING, "hello" ); |
| 50 | assert_eq!(*NUMBER, 6); |
| 51 | assert!(HASHMAP.get(&1).is_some()); |
| 52 | assert!(HASHMAP.get(&3).is_none()); |
| 53 | assert_eq!(&*ARRAY_BOXES, &[Box::new(1), Box::new(2), Box::new(3)]); |
| 54 | assert_eq!(*UNSAFE, std::u32::MAX); |
| 55 | } |
| 56 | |
| 57 | #[test] |
| 58 | fn test_repeat() { |
| 59 | assert_eq!(*NUMBER, 6); |
| 60 | assert_eq!(*NUMBER, 6); |
| 61 | assert_eq!(*NUMBER, 6); |
| 62 | } |
| 63 | |
| 64 | #[test] |
| 65 | fn test_meta() { |
| 66 | // this would not compile if STRING were not marked #[derive(Copy, Clone)] |
| 67 | let copy_of_string = STRING; |
| 68 | // just to make sure it was copied |
| 69 | assert!(&STRING as *const _ != ©_of_string as *const _); |
| 70 | |
| 71 | // this would not compile if STRING were not marked #[derive(Debug)] |
| 72 | assert_eq!(format!("{:?}" , STRING), "STRING { __private_field: () }" .to_string()); |
| 73 | } |
| 74 | |
| 75 | mod visibility { |
| 76 | lazy_static! { |
| 77 | pub static ref FOO: Box<u32> = Box::new(0); |
| 78 | static ref BAR: Box<u32> = Box::new(98); |
| 79 | } |
| 80 | |
| 81 | pub mod inner { |
| 82 | lazy_static! { |
| 83 | pub(in visibility) static ref BAZ: Box<u32> = Box::new(42); |
| 84 | pub(crate) static ref BAG: Box<u32> = Box::new(37); |
| 85 | } |
| 86 | } |
| 87 | |
| 88 | #[test] |
| 89 | fn sub_test() { |
| 90 | assert_eq!(**FOO, 0); |
| 91 | assert_eq!(**BAR, 98); |
| 92 | assert_eq!(**inner::BAZ, 42); |
| 93 | assert_eq!(**inner::BAG, 37); |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | #[test] |
| 98 | fn test_visibility() { |
| 99 | assert_eq!(*visibility::FOO, Box::new(0)); |
| 100 | assert_eq!(*visibility::inner::BAG, Box::new(37)); |
| 101 | } |
| 102 | |
| 103 | // This should not cause a warning about a missing Copy implementation |
| 104 | lazy_static! { |
| 105 | pub static ref VAR: i32 = { 0 }; |
| 106 | } |
| 107 | |
| 108 | #[derive(Copy, Clone, Debug, PartialEq)] |
| 109 | struct X; |
| 110 | struct Once(X); |
| 111 | const ONCE_INIT: Once = Once(X); |
| 112 | static DATA: X = X; |
| 113 | static ONCE: X = X; |
| 114 | fn require_sync() -> X { X } |
| 115 | fn transmute() -> X { X } |
| 116 | fn __static_ref_initialize() -> X { X } |
| 117 | fn test(_: Vec<X>) -> X { X } |
| 118 | |
| 119 | // All these names should not be shadowed |
| 120 | lazy_static! { |
| 121 | static ref ITEM_NAME_TEST: X = { |
| 122 | test(vec![X, Once(X).0, ONCE_INIT.0, DATA, ONCE, |
| 123 | require_sync(), transmute(), |
| 124 | // Except this, which will sadly be shadowed by internals: |
| 125 | // __static_ref_initialize() |
| 126 | ]) |
| 127 | }; |
| 128 | } |
| 129 | |
| 130 | #[test] |
| 131 | fn item_name_shadowing() { |
| 132 | assert_eq!(*ITEM_NAME_TEST, X); |
| 133 | } |
| 134 | |
| 135 | use std::sync::atomic::AtomicBool; |
| 136 | #[allow (deprecated)] |
| 137 | use std::sync::atomic::ATOMIC_BOOL_INIT; |
| 138 | use std::sync::atomic::Ordering::SeqCst; |
| 139 | |
| 140 | #[allow (deprecated)] |
| 141 | static PRE_INIT_FLAG: AtomicBool = ATOMIC_BOOL_INIT; |
| 142 | |
| 143 | lazy_static! { |
| 144 | static ref PRE_INIT: () = { |
| 145 | PRE_INIT_FLAG.store(true, SeqCst); |
| 146 | () |
| 147 | }; |
| 148 | } |
| 149 | |
| 150 | #[test] |
| 151 | fn pre_init() { |
| 152 | assert_eq!(PRE_INIT_FLAG.load(SeqCst), false); |
| 153 | lazy_static::initialize(&PRE_INIT); |
| 154 | assert_eq!(PRE_INIT_FLAG.load(SeqCst), true); |
| 155 | } |
| 156 | |
| 157 | lazy_static! { |
| 158 | static ref LIFETIME_NAME: for<'a> fn(&'a u8) = { fn f(_: &u8) {} f }; |
| 159 | } |
| 160 | |
| 161 | #[test] |
| 162 | fn lifetime_name() { |
| 163 | let _ = LIFETIME_NAME; |
| 164 | } |
| 165 | |