1pub mod tdd {
2 pub mod unit {
3
4 pub const IS_OK: &str = "The result match true";
5 pub const IS_KO: &str = "The result match false";
6 pub const IS_EQUALS: &str = "The values are equals";
7 pub const IS_UNEQUALS: &str = "The values are unequals";
8 pub const IS_BETWEEN: &str = "The values are between the expected values";
9 pub const IS_INFERIOR: &str = "The value are inferior to the expected value";
10 pub const IS_SUPERIOR: &str = "The value are superior to the expected value";
11 pub const IS_EMPTY: &str = "The value is empty";
12 pub const IS_DIRECTORY: &str = "The directory exist";
13 pub const IS_FILE: &str = "The file exist";
14 pub const IS_FULL: &str = "The value is at this maximum value";
15 pub const IS_PRIME: &str = "The value is a prime number";
16 pub const IS_PAIR: &str = "The value is a pair number";
17 pub const IS_START_WITH: &str = "The value start with the expected value";
18 pub const IS_FINNISH_WITH: &str = "The value finnish with the expected value";
19 pub const IS_IMPAIR: &str = "The value is not a pair number";
20 pub const IS_CONTAINS: &str = "The value contains the expected value";
21 pub const IS_ABSOLUTE: &str = "The path is absolute";
22 pub const IS_EXISTS: &str = "The path exists";
23 pub const IS_RELATIVE: &str = "The path is relative";
24 pub const IS_SYMLINK: &str = "The path is a symlink";
25 pub const IS_EXECUTABLE: &str = "The file is executable";
26 pub const THEORY_IS_TRUE: &str = "The theory is true";
27 pub const THEORY_IS_FALSE: &str = "The theory is false";
28 pub const IS_NOT_EXECUTABLE: &str = "The file is not executable";
29 pub const IS_NOT_SYMLINK: &str = "The path is a symlink";
30 pub const IS_NOT_RELATIVE: &str = "The path is not relative";
31 pub const IS_NOT_EXISTS: &str = "The path not exists";
32 pub const IS_NOT_ABSOLUTE: &str = "The path is not absolute";
33 pub const IS_NOT_FINNISH_WITH: &str = "The value don't finnish with the expected value";
34 pub const IS_NOT_CONTAINS: &str = "The value not contains the expected value";
35 pub const IS_NOT_PRIME: &str = "The value is not a prime number";
36 pub const IS_NOT_FULL: &str = "The value is not at this maximum value";
37 pub const IS_NOT_FILE: &str = "The file not exist";
38 pub const IS_NOT_DIRECTORY: &str = "The directory not exist";
39 pub const IS_NOT_EMPTY: &str = "The value is not empty";
40 pub const IS_NOT_BETWEEN: &str = "The values aren't between the expected values";
41 pub const IS_NOT_START_WITH: &str = "The value no start with the expected value";
42
43 pub const PROGRESS: u64 = 500;
44 pub const NO_PROGRESS: u64 = 0;
45
46 pub enum Style {
47 POINT,
48 ASTERIX,
49 OKAY,
50 }
51 use colored_truecolor::Colorize;
52 use is_executable::IsExecutable;
53 use std::cell::Cell;
54 use std::ops::Add;
55 use std::path::Path;
56 use std::thread::sleep;
57 use std::time::{Duration, Instant};
58 extern crate reqwest;
59
60 pub struct Unit {
61 description: String,
62 assertions: Cell<usize>,
63 failures: Cell<usize>,
64 start: Instant,
65 tdd: Cell<usize>,
66 sleep_time: u64,
67 style: Style,
68 }
69
70 impl Unit {
74 pub fn see(url: &str, expected: &str) -> bool {
75 reqwest::blocking::get(url)
76 .expect("failed to parse url")
77 .text()
78 .expect("failed to get text")
79 .contains(expected)
80 }
81 fn assertions(&mut self) -> usize {
85 self.assertions.get()
86 }
87
88 pub fn equals_bytes(&mut self, actual: &str, expected: &[u8]) -> &mut Unit {
89 self.assert(
90 String::from(actual).as_bytes().eq(expected),
91 IS_EQUALS,
92 IS_UNEQUALS,
93 )
94 }
95
96 pub fn unequals_bytes(&mut self, actual: &str, expected: &[u8]) -> &mut Unit {
97 self.assert(
98 String::from(actual).as_bytes().ne(expected),
99 IS_EQUALS,
100 IS_UNEQUALS,
101 )
102 }
103
104 pub fn begin_with(&mut self, actual: &str, expected: &str) -> &mut Unit {
105 self.assert(
106 String::from(actual).starts_with(expected),
107 IS_START_WITH,
108 IS_NOT_START_WITH,
109 )
110 }
111
112 pub fn finnish_with(&mut self, actual: &str, expected: &str) -> &mut Unit {
113 self.assert(
114 String::from(actual).ends_with(expected),
115 IS_FINNISH_WITH,
116 IS_NOT_FINNISH_WITH,
117 )
118 }
119
120 fn failures(&mut self) -> usize {
124 self.failures.get()
125 }
126
127 pub fn exe(&mut self, filename: &str) -> &mut Unit {
133 self.assert(
134 Path::new(filename).is_executable(),
135 IS_EXECUTABLE,
136 IS_NOT_EXECUTABLE,
137 )
138 }
139
140 pub fn not_exe(&mut self, filename: &str) -> &mut Unit {
141 self.assert(
142 !Path::new(filename).is_executable(),
143 IS_NOT_EXECUTABLE,
144 IS_EXECUTABLE,
145 )
146 }
147
148 fn assert(&mut self, tdd: bool, s: &str, f: &str) -> &mut Unit {
156 self.tdd.set(self.tdd.get() + 1);
157
158 match self.style {
159 Style::POINT => {
160 if tdd {
161 self.assertions.set(self.assertions.get() + 1);
162 print!("{}", ".".magenta().bold());
163 } else {
164 self.failures.set(self.failures.get() + 1);
165 print!("{}", "F".magenta().bold());
166 }
167 sleep(Duration::from_millis(self.sleep_time));
168 }
169 Style::OKAY => {
170 if tdd {
171 self.assertions.set(self.assertions.get() + 1);
172 println!(
173 "{} {} {} {}\n",
174 "[".white().bold(),
175 "OK".green().bold(),
176 "]".white().bold(),
177 s.blue().bold()
178 );
179 } else {
180 self.failures.set(self.failures.get() + 1);
181 println!(
182 "{} {} {} {}\n",
183 "[".white().bold(),
184 "KO".red().bold(),
185 "]".white().bold(),
186 f.yellow().bold()
187 );
188 }
189 sleep(Duration::from_millis(self.sleep_time));
190 }
191 Style::ASTERIX => {
192 if tdd {
193 self.assertions.set(self.assertions.get() + 1);
194 println!("{} {}\n", "*".green().bold(), s.blue().bold());
195 } else {
196 self.failures.set(self.failures.get() + 1);
197 println!("{} {}\n", "*".red().bold(), f.yellow().bold());
198 }
199 sleep(Duration::from_millis(self.sleep_time));
200 }
201 }
202 sleep(Duration::from_millis(self.sleep_time));
203 self
204 }
205
206 pub fn describe(
214 &mut self,
215 description: &str,
216 it: fn(&mut Unit) -> &mut Unit,
217 ) -> &mut Unit {
218 self.title(description);
219 it(self)
220 }
221
222 pub fn title(&mut self, description: &str) {
223 if self.assertions() == 0 && self.failures() == 0 {
224 println!("{}\n", description.blue().bold());
225 } else {
226 println!("\n\n{}\n", description.blue().bold());
227 }
228 }
229 pub fn theory(&mut self, description: &str, it: fn() -> bool) -> &mut Unit {
230 self.title(description);
231 self.assert(it(), THEORY_IS_TRUE, THEORY_IS_FALSE)
232 }
233
234 pub fn chaos(&mut self, description: &str, it: fn() -> bool) -> &mut Unit {
241 self.title(description);
242 self.assert(!it(), THEORY_IS_FALSE, THEORY_IS_TRUE)
243 }
244
245 pub fn new(description: &str, time: u64, s: Style) -> Unit {
254 println!("\n{}\n", description.magenta().bold());
255
256 Self {
257 description: description.to_string(),
258 assertions: Cell::new(0),
259 failures: Cell::new(0),
260 start: Instant::now(),
261 tdd: Cell::new(0),
262 sleep_time: time,
263 style: s,
264 }
265 }
266
267 pub fn end(&mut self) -> Result<String, String> {
272 let asserts = self.assertions();
273 let fails = self.failures();
274
275 println!(
276 "\n\n{} : {} {} : {} {} : {} {} : {}\n",
277 "Assertions".blue().bold(),
278 asserts.to_string().green().bold(),
279 "Failures".blue().bold(),
280 fails.to_string().red().bold(),
281 "Execution time".blue().bold(),
282 self.start
283 .elapsed()
284 .as_millis()
285 .to_string()
286 .add(" ms")
287 .magenta()
288 .bold(),
289 "All tests executed".blue().bold(),
290 self.tdd.get().to_string().white().bold()
291 );
292
293 return if self.failures() >= 1 {
294 Err(String::from(self.description.as_str()))
295 } else {
296 Ok(String::from(self.description.as_str()))
297 };
298 }
299
300 pub fn ok(&mut self, b: bool) -> &mut Unit {
307 self.assert(b, IS_OK, IS_KO)
308 }
309
310 pub fn ko(&mut self, b: bool) -> &mut Unit {
317 self.assert(!b, IS_KO, IS_OK)
318 }
319
320 pub fn equals<T: PartialEq>(&mut self, a: T, b: T) -> &mut Unit {
327 self.assert(a == b, IS_EQUALS, IS_UNEQUALS)
328 }
329
330 pub fn between<T: PartialOrd>(&mut self, actual: T, min: T, max: T) -> &mut Unit {
340 self.assert(actual > min && actual < max, IS_BETWEEN, IS_NOT_BETWEEN)
341 }
342
343 pub fn unequals<T: PartialEq>(&mut self, a: T, b: T) -> &mut Unit {
351 self.assert(a != b, IS_UNEQUALS, IS_EQUALS)
352 }
353
354 pub fn inferior<T: PartialOrd>(&mut self, actual: T, max: T) -> &mut Unit {
361 self.assert(actual < max, IS_INFERIOR, IS_SUPERIOR)
362 }
363
364 pub fn superior<T: PartialOrd>(&mut self, actual: T, min: T) -> &mut Unit {
371 self.assert(actual > min, IS_SUPERIOR, IS_INFERIOR)
372 }
373
374 pub fn not_empty(&mut self, x: &str) -> &mut Unit {
381 self.assert(!x.to_string().is_empty(), IS_NOT_EMPTY, IS_EMPTY)
382 }
383
384 pub fn contains(&mut self, x: &str, expected: &str) -> &mut Unit {
392 self.assert(
393 x.to_string().contains(expected),
394 IS_CONTAINS,
395 IS_NOT_CONTAINS,
396 )
397 }
398
399 pub fn not_contains(&mut self, x: &str, expected: &str) -> &mut Unit {
407 self.assert(
408 !x.to_string().contains(expected),
409 IS_CONTAINS,
410 IS_NOT_CONTAINS,
411 )
412 }
413
414 pub fn empty(&mut self, x: &str) -> &mut Unit {
421 self.assert(x.to_string().is_empty(), IS_EMPTY, IS_NOT_EMPTY)
422 }
423
424 pub fn is_directory(&mut self, d: &str) -> &mut Unit {
430 self.assert(Path::new(d).is_dir(), IS_DIRECTORY, IS_NOT_DIRECTORY)
431 }
432
433 pub fn is_not_directory(&mut self, d: &str) -> &mut Unit {
439 self.assert(!Path::new(d).is_dir(), IS_NOT_DIRECTORY, IS_DIRECTORY)
440 }
441
442 pub fn is_file(&mut self, f: &str) -> &mut Unit {
448 self.assert(Path::new(f).is_file(), IS_FILE, IS_NOT_FILE)
449 }
450
451 pub fn path_start_with(&mut self, path: &str, base: &str) -> &mut Unit {
461 self.assert(
462 Path::new(path).starts_with(base),
463 IS_START_WITH,
464 IS_NOT_START_WITH,
465 )
466 }
467
468 pub fn path_absolute(&mut self, path: &str) -> &mut Unit {
476 self.assert(Path::new(path).is_absolute(), IS_ABSOLUTE, IS_NOT_ABSOLUTE)
477 }
478
479 pub fn path_not_absolute(&mut self, path: &str) -> &mut Unit {
487 self.assert(!Path::new(path).is_absolute(), IS_NOT_ABSOLUTE, IS_ABSOLUTE)
488 }
489
490 pub fn path_exists(&mut self, path: &str) -> &mut Unit {
498 self.assert(Path::new(path).exists(), IS_EXISTS, IS_NOT_EXISTS)
499 }
500
501 pub fn path_not_relative(&mut self, path: &str) -> &mut Unit {
508 self.assert(!Path::new(path).is_relative(), IS_RELATIVE, IS_NOT_RELATIVE)
509 }
510
511 pub fn is_executable(&mut self, path: &str) -> &mut Unit {
518 self.assert(
519 Path::new(path).is_executable(),
520 IS_EXECUTABLE,
521 IS_NOT_EXECUTABLE,
522 )
523 }
524
525 pub fn is_not_executable(&mut self, path: &str) -> &mut Unit {
532 self.assert(
533 !Path::new(path).is_executable(),
534 IS_NOT_EXECUTABLE,
535 IS_EXECUTABLE,
536 )
537 }
538
539 pub fn path_symlink(&mut self, path: &str) -> &mut Unit {
546 self.assert(!Path::new(path).is_symlink(), IS_SYMLINK, IS_NOT_SYMLINK)
547 }
548
549 pub fn path_relative(&mut self, path: &str) -> &mut Unit {
557 self.assert(Path::new(path).is_relative(), IS_RELATIVE, IS_NOT_RELATIVE)
558 }
559 pub fn path_no_exists(&mut self, path: &str) -> &mut Unit {
567 self.assert(!Path::new(path).exists(), IS_NOT_EXISTS, IS_EXISTS)
568 }
569
570 pub fn file_contains(&mut self, file: &str, expected: &str) -> &mut Unit {
578 let content = std::fs::read_to_string(file).expect("Failed to parse file");
579
580 self.assert(content.contains(expected), IS_CONTAINS, IS_NOT_CONTAINS)
581 }
582
583 pub fn file_no_contains(&mut self, file: &str, expected: &str) -> &mut Unit {
591 let content = std::fs::read_to_string(file).expect("Failed to parse file");
592 self.assert(content.contains(expected), IS_NOT_CONTAINS, IS_CONTAINS)
593 }
594 pub fn vec_length_equals<T: PartialEq>(&mut self, a: Vec<T>, b: Vec<T>) -> &mut Unit {
601 self.assert(a.len() == b.len(), IS_EQUALS, IS_UNEQUALS)
602 }
603
604 pub fn vec_length_unequals<T: PartialEq>(&mut self, a: Vec<T>, b: Vec<T>) -> &mut Unit {
611 self.assert(a.len() != b.len(), IS_UNEQUALS, IS_EQUALS)
612 }
613
614 pub fn vec_contains<T: PartialEq>(&mut self, a: Vec<T>, b: T) -> &mut Unit {
621 self.assert(a.contains(&b), IS_CONTAINS, IS_NOT_CONTAINS)
622 }
623
624 pub fn vec_no_contains<T: PartialEq>(&mut self, a: Vec<T>, b: T) -> &mut Unit {
631 self.assert(!a.contains(&b), IS_NOT_CONTAINS, IS_CONTAINS)
632 }
633
634 pub fn vec_start_with<T: PartialEq>(&mut self, a: Vec<T>, b: T) -> &mut Unit {
641 self.assert(a.starts_with(&[b]), IS_START_WITH, IS_NOT_START_WITH)
642 }
643
644 pub fn vec_no_start_with<T: PartialEq>(&mut self, a: Vec<T>, b: T) -> &mut Unit {
651 self.assert(!a.starts_with(&[b]), IS_NOT_CONTAINS, IS_CONTAINS)
652 }
653
654 pub fn vec_end_with<T: PartialEq>(&mut self, a: Vec<T>, b: T) -> &mut Unit {
661 self.assert(a.ends_with(&[b]), IS_FINNISH_WITH, IS_NOT_FINNISH_WITH)
662 }
663
664 pub fn vec_no_end_with<T: PartialEq>(&mut self, a: Vec<T>, b: T) -> &mut Unit {
671 self.assert(!a.ends_with(&[b]), IS_NOT_FINNISH_WITH, IS_FINNISH_WITH)
672 }
673
674 pub fn vec_empty<T: PartialEq>(&mut self, a: Vec<T>) -> &mut Unit {
680 self.assert(a.is_empty(), IS_EMPTY, IS_NOT_EMPTY)
681 }
682
683 pub fn vec_not_empty<T: PartialEq>(&mut self, a: Vec<T>) -> &mut Unit {
689 self.assert(!a.is_empty(), IS_NOT_EMPTY, IS_EMPTY)
690 }
691
692 pub fn full(&mut self, callback: fn() -> usize, max: usize) -> &mut Unit {
699 self.assert((callback() / max) == 1, IS_FULL, IS_NOT_FULL)
700 }
701
702 pub fn not_full(&mut self, callback: fn() -> usize, max: usize) -> &mut Unit {
709 self.assert((callback() / max) < 1, IS_NOT_FULL, IS_FULL)
710 }
711
712 pub fn prime(&mut self, x: usize) -> &mut Unit {
718 self.assert(x % 2 != 0 && x % 3 != 0, IS_NOT_PRIME, IS_PRIME)
719 }
720
721 pub fn pair(&mut self, x: usize) -> &mut Unit {
727 self.assert(x % 2 == 0, IS_PAIR, IS_IMPAIR)
728 }
729
730 pub fn impair(&mut self, x: usize) -> &mut Unit {
736 if x % 2 == 0 {
737 return self.assert(false, IS_PAIR, IS_PAIR);
738 }
739 if x % 3 == 0 {
740 return self.assert(true, IS_IMPAIR, IS_PAIR);
741 }
742 return self.assert(false, IS_PRIME, IS_PRIME);
743 }
744 }
745
746 #[macro_export]
753 macro_rules! assert_true {
754 ($description:expr,$items:expr) => {
755 let mut u = Unit::new($description, NO_PROGRESS, POINT);
756 for &item in $items.iter() {
757 u.ok(item);
758 }
759 u.end().expect("A result not match true");
760 };
761 }
762
763 #[macro_export]
770 macro_rules! assert_false {
771 ($description:expr,$items:expr) => {
772 let mut u = Unit::new($description, NO_PROGRESS, POINT);
773 for &item in $items.iter() {
774 u.ko(item);
775 }
776 u.end().expect("A result not match false");
777 };
778 }
779
780 #[macro_export]
787 macro_rules! assert_directory_exist {
788 ($description:expr,$items:expr) => {
789 let mut u = Unit::new($description, NO_PROGRESS, POINT);
790 for &item in $items.iter() {
791 u.is_directory(item);
792 }
793 u.end().expect("A directory has not been founded");
794 };
795 }
796
797 #[macro_export]
804 macro_rules! assert_files_exist {
805 ($description:expr,$items:expr) => {
806 let mut u = Unit::new($description, NO_PROGRESS, POINT);
807 for &item in $items.iter() {
808 u.is_file(item);
809 }
810 u.end().expect("A file has not been founded");
811 };
812 }
813
814 #[macro_export]
822 macro_rules! assert_contains {
823 ($description:expr,$items:expr,$v:expr) => {
824 let mut u = Unit::new($description, NO_PROGRESS, POINT);
825 for &item in $items.iter() {
826 u.contains($v, item);
827 }
828 u.end().expect("A value has not been founded");
829 };
830 }
831
832 #[macro_export]
840 macro_rules! assert_not_contains {
841 ($description:expr,$items:expr,$v:expr) => {
842 let mut u = Unit::new($description, NO_PROGRESS, POINT);
843 for &item in $items.iter() {
844 u.not_contains($v, item);
845 }
846 u.end().expect("A value has not been founded");
847 };
848 }
849
850 #[macro_export]
857 macro_rules! assert_not_exe {
858 ($description:expr,$items:expr) => {
859 let mut u = Unit::new($description, NO_PROGRESS, POINT);
860 for &item in $items.iter() {
861 u.not_exe(item);
862 }
863 u.end().expect("A value is not an executable");
864 };
865 }
866
867 #[macro_export]
875 macro_rules! assert_equals {
876 ($description:expr,$items:expr,$v:expr) => {
877 let mut u = Unit::new($description, NO_PROGRESS, POINT);
878 for &item in $items.iter() {
879 u.equals($v, item);
880 }
881 u.end().expect("A value not equal to the expected value");
882 };
883 }
884
885 #[macro_export]
893 macro_rules! assert_unequals {
894 ($description:expr,$items:expr,$v:expr) => {
895 let mut u = Unit::new($description, NO_PROGRESS, POINT);
896 for &item in $items.iter() {
897 u.unequals($v, item);
898 }
899 u.end().expect("A value equal to the expected value");
900 };
901 }
902
903 #[macro_export]
911 macro_rules! unit {
912 ($description:expr) => {
913 Unit::new($description, NO_PROGRESS, POINT)
914 };
915 }
916
917 #[macro_export]
925 macro_rules! assert_exe {
926 ($description:expr,$items:expr) => {
927 let mut u = Unit::new($description, NO_PROGRESS, POINT);
928 for &item in $items.iter() {
929 u.exe(item);
930 }
931 u.end().expect("A value is not an executable");
932 };
933 }
934 }
935}
936
937#[cfg(test)]
938mod tests {
939
940 use crate::{
941 assert_contains, assert_directory_exist, assert_equals, assert_false, assert_files_exist,
942 assert_not_contains, assert_not_exe, assert_true, assert_unequals,
943 tdd::unit::{Style::POINT, Unit, NO_PROGRESS},
944 unit,
945 };
946 use std::env::consts::OS;
947 fn battery_full() -> usize {
948 100
949 }
950 fn battery_not_full() -> usize {
951 50
952 }
953
954 fn together() -> bool {
955 false
956 }
957
958 fn pythagore() -> bool {
959 4 * 4 + 3 * 3 == 5 * 5
960 }
961
962 fn admin(u: &mut Unit) -> &mut Unit {
963 u.inferior(1, 2).prime(1).superior(1, 0).between(1, 0, 2)
964 }
965
966 fn boolean(u: &mut Unit) -> &mut Unit {
967 u.ok(pythagore())
968 .ko(together())
969 .theory("Check the theorm of pythagore", pythagore)
970 .chaos("The bigbang", together)
971 .is_directory(".")
972 .is_file("README.md")
973 }
974
975 fn git_test_install(u: &mut Unit) -> &mut Unit {
976 u.exe("/usr/bin/git")
977 }
978
979 fn e(u: &mut Unit) -> &mut Unit {
980 u.empty("").not_empty(OS)
981 }
982 fn battery(u: &mut Unit) -> &mut Unit {
983 u.full(battery_full, 100).not_full(battery_not_full, 100)
984 }
985 fn equals(u: &mut Unit) -> &mut Unit {
986 u.equals(true, pythagore())
987 .unequals(false, pythagore())
988 .equals_bytes("hello", &[104, 101, 108, 108, 111])
989 .unequals_bytes("hallo", &[104, 101, 108, 108, 111])
990 }
991
992 fn numbers(u: &mut Unit) -> &mut Unit {
993 u.prime(1).prime(7).prime(11);
994 u.pair(2).pair(4).pair(6);
995 u.impair(3).impair(9)
996 }
997
998 #[test]
999 pub fn test_see() {
1000 assert!(Unit::see("https://www.google.com", "google"));
1001 }
1002
1003 #[test]
1004 pub fn unit() {
1005 unit!("Test the unit framework")
1006 .describe("Check theories", boolean)
1007 .describe("Test charge", battery)
1008 .describe("Check admin users accout number", admin)
1009 .describe("Test number", numbers)
1010 .describe("They are equals", equals)
1011 .describe("Check empty", e)
1012 .describe("Check if git is installed", git_test_install)
1013 .end()
1014 .expect("failed");
1015 }
1016
1017 #[test]
1018 pub fn test_macros() {
1019 assert_true!("All values must matches true", vec![true, true, true]);
1020 assert_false!("All values must matches false", vec![false, false, false]);
1021 assert_directory_exist!(
1022 "Check if user use linux",
1023 vec!["/", "/home", "/etc", ".", ".."]
1024 );
1025 assert_files_exist!(
1026 "Check if user use linux",
1027 vec!["/etc/hosts", "/etc/locale.conf"]
1028 );
1029
1030 assert_not_exe!(
1031 "Check if configugrations files is not an executable",
1032 vec!["/etc/hosts", "/etc/locale.gen"]
1033 );
1034
1035 assert_contains!("Check if user use linux", vec!["linux"], OS);
1036 assert_not_contains!(
1037 "Check if user use linux",
1038 vec!["windows", "ios", "freebsd", "openbsd", "android", "solaris", "netbsd", "macos"],
1039 OS
1040 );
1041
1042 assert_equals!(
1043 "All value must be equals to linux",
1044 vec!["linux", "linux", "linux"],
1045 OS
1046 );
1047
1048 assert_unequals!(
1049 "All os must be only equals to linux",
1050 vec!["windows", "ios", "freebsd", "openbsd", "android", "solaris", "netbsd", "macos"],
1051 OS
1052 );
1053 }
1054}