1use crate::{JSONVariantEnvironment, SearchUserEnvironment};
9use firefox_versioning::version::Version;
10
11pub(crate) fn matches_user_environment(
17 environment: &JSONVariantEnvironment,
18 user_environment: &SearchUserEnvironment,
19) -> bool {
20 if !environment.experiment.is_empty() && user_environment.experiment != environment.experiment {
21 return false;
22 }
23
24 if !environment.excluded_distributions.is_empty()
25 && environment
26 .excluded_distributions
27 .contains(&user_environment.distribution_id)
28 {
29 return false;
30 }
31
32 matches_region_and_locale(
33 &user_environment.region,
34 &user_environment.locale,
35 environment,
36 ) && is_empty_or_contains(
37 &environment.distributions,
38 &user_environment.distribution_id,
39 ) && matches_version(
40 &user_environment.version,
41 &environment.min_version,
42 &environment.max_version,
43 ) && is_empty_or_contains(&environment.channels, &user_environment.update_channel)
44 && is_empty_or_contains(&environment.applications, &user_environment.app_name)
45 && is_empty_or_contains(&environment.device_type, &user_environment.device_type)
46}
47
48fn matches_region_and_locale(
51 user_region: &str,
52 user_locale: &str,
53 environment: &JSONVariantEnvironment,
54) -> bool {
55 if does_array_include(&environment.excluded_regions, user_region)
56 || does_array_include(&environment.excluded_locales, user_locale)
57 {
58 return false;
59 }
60
61 if !environment.all_regions_and_locales
67 && environment.regions.is_empty()
68 && environment.locales.is_empty()
69 {
70 return true;
71 }
72
73 if does_array_include(&environment.regions, user_region)
74 && does_array_include(&environment.locales, user_locale)
75 {
76 return true;
77 }
78
79 if environment.regions.is_empty() && does_array_include(&environment.locales, user_locale) {
80 return true;
81 }
82
83 if environment.locales.is_empty() && does_array_include(&environment.regions, user_region) {
84 return true;
85 }
86
87 if environment.all_regions_and_locales {
88 return true;
89 }
90
91 false
92}
93
94fn matches_version(
95 user_version: &str,
96 environment_min_version: &str,
97 environment_max_version: &str,
98) -> bool {
99 use std::ops::{Bound, RangeBounds};
100
101 let (min_version, max_version) = match (
102 environment_min_version.is_empty(),
103 environment_max_version.is_empty(),
104 ) {
105 (true, true) => return true,
106 (true, false) => (
107 Bound::Unbounded,
108 Version::try_from(environment_max_version).map_or(Bound::Unbounded, Bound::Included),
109 ),
110 (false, true) => (
111 Version::try_from(environment_min_version).map_or(Bound::Unbounded, Bound::Included),
112 Bound::Unbounded,
113 ),
114 (false, false) => (
115 Version::try_from(environment_min_version).map_or(Bound::Unbounded, Bound::Included),
116 Version::try_from(environment_max_version).map_or(Bound::Unbounded, Bound::Included),
117 ),
118 };
119
120 !user_version.is_empty()
121 && Version::try_from(user_version).map_or(true, |user_version| {
122 (min_version, max_version).contains(&user_version)
123 })
124}
125
126fn is_empty_or_contains<T: std::cmp::PartialEq>(env_value: &[T], user_value: &T) -> bool {
127 env_value.is_empty() || env_value.contains(user_value)
128}
129
130fn does_array_include(config_array: &[String], compare_item: &str) -> bool {
131 !config_array.is_empty()
132 && config_array
133 .iter()
134 .any(|x| x.to_lowercase() == compare_item)
135}
136
137#[cfg(test)]
138mod tests {
139 use std::vec;
140
141 use super::*;
142 use crate::*;
143
144 #[test]
145 fn test_matches_user_environment_all_locales() {
146 assert!(
147 matches_user_environment(
148 &crate::JSONVariantEnvironment {
149 all_regions_and_locales: true,
150 excluded_locales: vec![],
151 excluded_regions: vec![],
152 locales: vec![],
153 regions: vec![],
154 ..Default::default()
155 },
156 &SearchUserEnvironment {
157 locale: "fi".into(),
158 region: "FR".into(),
159 ..Default::default()
160 }
161 ),
162 "Should return true when all_regions_and_locales is true"
163 );
164
165 assert!(
166 matches_user_environment(
167 &crate::JSONVariantEnvironment {
168 all_regions_and_locales: false,
169 excluded_locales: vec![],
170 excluded_regions: vec![],
171 locales: vec![],
172 regions: vec![],
173 ..Default::default()
174 },
175 &SearchUserEnvironment {
176 locale: "fi".into(),
177 region: "fr".into(),
178 ..Default::default()
179 }
180 ),
181 "Should return true when all_regions_and_locales is false (default) and no regions/locales are specified"
182 );
183
184 assert!(
185 !matches_user_environment(
186 &crate::JSONVariantEnvironment {
187 all_regions_and_locales: true,
188 excluded_locales: vec!["fi".to_string()],
189 excluded_regions: vec![],
190 locales: vec![],
191 regions: vec![],
192 ..Default::default()
193 },
194 &SearchUserEnvironment {
195 locale: "fi".into(),
196 region: "fr".into(),
197 ..Default::default()
198 }
199 ),
200 "Should return false when all_regions_and_locales is true and the locale is excluded"
201 );
202
203 assert!(
204 !matches_user_environment(
205 &crate::JSONVariantEnvironment {
206 all_regions_and_locales: true,
207 excluded_locales: vec!["FI".to_string()],
208 excluded_regions: vec![],
209 locales: vec![],
210 regions: vec![],
211 ..Default::default()
212 },
213 &SearchUserEnvironment {
214 locale: "fi".into(),
215 region: "fr".into(),
216 ..Default::default()
217 }
218 ),
219 "Should return false when all_regions_and_locales is true and the excluded locale is a different case"
220 );
221
222 assert!(
223 matches_user_environment(
224 &crate::JSONVariantEnvironment {
225 all_regions_and_locales: true,
226 excluded_locales: vec!["en-US".to_string()],
227 excluded_regions: vec![],
228 locales: vec![],
229 regions: vec![],
230 ..Default::default()
231 },
232 &SearchUserEnvironment {
233 locale: "fi".into(),
234 region: "fr".into(),
235 ..Default::default()
236 }
237 ),
238 "Should return true when all_regions_and_locales is true and the locale is not excluded"
239 );
240
241 assert!(
242 !matches_user_environment(
243 &crate::JSONVariantEnvironment {
244 all_regions_and_locales: true,
245 excluded_regions: vec!["us".to_string(), "fr".to_string()],
246 locales: vec![],
247 regions: vec![],
248 ..Default::default()
249 },
250 &SearchUserEnvironment {
251 locale: "fi".into(),
252 region: "fr".into(),
253 ..Default::default()
254 }
255 ),
256 "Should return false when all_regions_and_locales is true and the region is excluded"
257 );
258
259 assert!(
260 !matches_user_environment(
261 &crate::JSONVariantEnvironment {
262 all_regions_and_locales: true,
263 excluded_locales: vec![],
264 excluded_regions: vec!["US".to_string(), "FR".to_string()],
265 locales: vec![],
266 regions: vec![],
267 ..Default::default()
268 },
269 &SearchUserEnvironment {
270 locale: "fi".into(),
271 region: "fr".into(),
272 ..Default::default()
273 }
274 ),
275 "Should return false when all_regions_and_locales is true and the excluded region is a different case"
276 );
277
278 assert!(
279 matches_user_environment(
280 &crate::JSONVariantEnvironment {
281 all_regions_and_locales: true,
282 excluded_locales: vec![],
283 excluded_regions: vec!["us".to_string()],
284 locales: vec![],
285 regions: vec![],
286 ..Default::default()
287 },
288 &SearchUserEnvironment {
289 locale: "fi".into(),
290 region: "fr".into(),
291 ..Default::default()
292 }
293 ),
294 "Should return true when all_regions_and_locales is true and the region is not excluded"
295 );
296 }
297
298 #[test]
299 fn test_matches_user_environment_locales() {
300 assert!(
301 matches_user_environment(
302 &crate::JSONVariantEnvironment {
303 all_regions_and_locales: false,
304 excluded_locales: vec![],
305 excluded_regions: vec![],
306 locales: vec!["en-gb".to_string(), "fi".to_string()],
307 regions: vec![],
308 ..Default::default()
309 },
310 &SearchUserEnvironment {
311 locale: "fi".into(),
312 region: "fr".into(),
313 ..Default::default()
314 }
315 ),
316 "Should return true when the user locale matches one from the config"
317 );
318
319 assert!(
320 matches_user_environment(
321 &crate::JSONVariantEnvironment {
322 all_regions_and_locales: false,
323 excluded_locales: vec![],
324 excluded_regions: vec![],
325 locales: vec!["en-GB".to_string(), "FI".to_string()],
326 regions: vec![],
327 ..Default::default()
328 },
329 &SearchUserEnvironment {
330 locale: "fi".into(),
331 region: "fr".into(),
332 ..Default::default()
333 }
334 ),
335 "Should return true when the user locale matches one from the config and is a different case"
336 );
337
338 assert!(
339 !matches_user_environment(
340 &crate::JSONVariantEnvironment {
341 all_regions_and_locales: false,
342 excluded_locales: vec![],
343 excluded_regions: vec![],
344 locales: vec!["en-gb".to_string(), "en-ca".to_string()],
345 regions: vec![],
346 ..Default::default()
347 },
348 &SearchUserEnvironment {
349 locale: "fi".into(),
350 region: "fr".into(),
351 ..Default::default()
352 }
353 ),
354 "Should return false when the user locale does not match one from the config"
355 );
356 }
357
358 #[test]
359 fn test_matches_user_environment_regions() {
360 assert!(
361 matches_user_environment(
362 &crate::JSONVariantEnvironment {
363 all_regions_and_locales: false,
364 excluded_locales: vec![],
365 excluded_regions: vec![],
366 locales: vec![],
367 regions: vec!["gb".to_string(), "fr".to_string()],
368 ..Default::default()
369 },
370 &SearchUserEnvironment {
371 locale: "fi".into(),
372 region: "fr".into(),
373 ..Default::default()
374 }
375 ),
376 "Should return true when the user region matches one from the config"
377 );
378
379 assert!(
380 matches_user_environment(
381 &crate::JSONVariantEnvironment {
382 all_regions_and_locales: false,
383 excluded_locales: vec![],
384 excluded_regions: vec![],
385 locales: vec![],
386 regions: vec!["GB".to_string(), "FR".to_string()],
387 ..Default::default()
388 },
389 &SearchUserEnvironment {
390 locale: "fi".into(),
391 region: "fr".into(),
392 ..Default::default()
393 }
394 ),
395 "Should return true when the user region matches one from the config and is a different case"
396 );
397
398 assert!(
399 !matches_user_environment(
400 &crate::JSONVariantEnvironment {
401 all_regions_and_locales: false,
402 excluded_locales: vec![],
403 excluded_regions: vec![],
404 locales: vec!["gb".to_string(), "ca".to_string()],
405 regions: vec![],
406 ..Default::default()
407 },
408 &SearchUserEnvironment {
409 locale: "fi".into(),
410 region: "fr".into(),
411 ..Default::default()
412 }
413 ),
414 "Should return false when the user region does not match one from the config"
415 );
416 }
417
418 #[test]
419 fn test_matches_user_environment_locales_with_excluded_regions() {
420 assert!(
421 matches_user_environment(
422 &crate::JSONVariantEnvironment {
423 all_regions_and_locales: false,
424 excluded_locales: vec![],
425 excluded_regions: vec!["gb".to_string(), "ca".to_string()],
426 locales: vec!["en-gb".to_string(), "fi".to_string()],
427 regions: vec![],
428 ..Default::default()
429 },
430 &SearchUserEnvironment {
431 locale: "fi".into(),
432 region: "fr".into(),
433 ..Default::default()
434 }
435 ),
436 "Should return true when the locale matches and the region is not excluded"
437 );
438
439 assert!(
440 !matches_user_environment(
441 &crate::JSONVariantEnvironment {
442 all_regions_and_locales: false,
443 excluded_locales: vec![],
444 excluded_regions: vec!["gb".to_string(), "fr".to_string()],
445 locales: vec!["en-gb".to_string(), "fi".to_string()],
446 regions: vec![],
447 ..Default::default()
448 },
449 &SearchUserEnvironment {
450 locale: "fi".into(),
451 region: "fr".into(),
452 ..Default::default()
453 }
454 ),
455 "Should return false when the locale matches and the region is excluded"
456 );
457 }
458
459 #[test]
460 fn test_matches_user_environment_regions_with_excluded_locales() {
461 assert!(
462 matches_user_environment(
463 &crate::JSONVariantEnvironment {
464 all_regions_and_locales: false,
465 excluded_locales: vec!["en-gb".to_string(), "de".to_string()],
466 excluded_regions: vec![],
467 locales: vec![],
468 regions: vec!["gb".to_string(), "fr".to_string()],
469 ..Default::default()
470 },
471 &SearchUserEnvironment {
472 locale: "fi".into(),
473 region: "fr".into(),
474 ..Default::default()
475 }
476 ),
477 "Should return true when the region matches and the locale is not excluded"
478 );
479
480 assert!(
481 !matches_user_environment(
482 &crate::JSONVariantEnvironment {
483 all_regions_and_locales: false,
484 excluded_locales: vec!["en-gb".to_string(), "fi".to_string()],
485 excluded_regions: vec![],
486 locales: vec![],
487 regions: vec!["gb".to_string(), "fr".to_string()],
488 ..Default::default()
489 },
490 &SearchUserEnvironment {
491 locale: "fi".into(),
492 region: "fr".into(),
493 ..Default::default()
494 }
495 ),
496 "Should return false when the region matches and the locale is excluded"
497 );
498 }
499
500 #[test]
501 fn test_matches_user_environment_distributions() {
502 assert!(
503 matches_user_environment(
504 &crate::JSONVariantEnvironment {
505 distributions: vec!["distro-1".to_string()],
506 ..Default::default()
507 },
508 &SearchUserEnvironment {
509 distribution_id: "distro-1".into(),
510 ..Default::default()
511 }
512 ),
513 "Should return true when the distribution matches one in the environment"
514 );
515
516 assert!(
517 matches_user_environment(
518 &crate::JSONVariantEnvironment {
519 distributions: vec!["distro-2".to_string(), "distro-3".to_string()],
520 ..Default::default()
521 },
522 &SearchUserEnvironment {
523 distribution_id: "distro-3".into(),
524 ..Default::default()
525 }
526 ),
527 "Should return true when the distribution matches one in the environment when there are multiple"
528 );
529
530 assert!(
531 !matches_user_environment(
532 &crate::JSONVariantEnvironment {
533 distributions: vec!["distro-2".to_string(), "distro-3".to_string()],
534 ..Default::default()
535 },
536 &SearchUserEnvironment {
537 distribution_id: "distro-4".into(),
538 ..Default::default()
539 }
540 ),
541 "Should return false when the distribution does not match any in the environment"
542 );
543
544 assert!(
545 matches_user_environment(
546 &crate::JSONVariantEnvironment {
547 regions: vec!["fr".to_string()],
548 distributions: vec!["distro-1".to_string(), "distro-2".to_string()],
549 ..Default::default()
550 },
551 &SearchUserEnvironment {
552 locale: "fi".into(),
553 region: "fr".into(),
554 distribution_id: "distro-2".into(),
555 ..Default::default()
556 }
557 ),
558 "Should return true when the distribution and region matches the environment"
559 );
560 }
561
562 #[test]
563 fn test_matches_user_environment_excluded_distributions() {
564 assert!(
565 matches_user_environment(
566 &crate::JSONVariantEnvironment {
567 distributions: vec!["distro-1".to_string(), "distro-2".to_string()],
568 excluded_distributions: vec!["
569 distro-3".to_string(), "distro-4".to_string()
570 ],
571 ..Default::default()
572 },
573 &SearchUserEnvironment {
574 distribution_id: "distro-2".into(),
575 ..Default::default()
576 }
577 ),
578 "Should return true when the distribution matches the distribution list but not the excluded distributions"
579 );
580
581 assert!(
582 !matches_user_environment(
583 &crate::JSONVariantEnvironment {
584 distributions: vec!["distro-1".to_string(), "distro-2".to_string()],
585 excluded_distributions: vec!["distro-3".to_string(), "distro-4".to_string()],
586 ..Default::default()
587 },
588 &SearchUserEnvironment {
589 distribution_id: "distro-3".into(),
590 ..Default::default()
591 }
592 ),
593 "Should return false when the distribution matches the the excluded distributions"
594 );
595 }
596
597 #[test]
598 fn test_matches_user_environment_application_name() {
599 assert!(
600 matches_user_environment(
601 &crate::JSONVariantEnvironment {
602 applications: vec![SearchApplicationName::Firefox],
603 ..Default::default()
604 },
605 &SearchUserEnvironment {
606 app_name: SearchApplicationName::Firefox,
607 ..Default::default()
608 }
609 ),
610 "Should return true when the application name matches the one in the environment"
611 );
612
613 assert!(
614 matches_user_environment(
615 &crate::JSONVariantEnvironment {
616 applications: vec![
617 SearchApplicationName::FirefoxAndroid,
618 SearchApplicationName::Firefox
619 ],
620 ..Default::default()
621 },
622 &SearchUserEnvironment {
623 app_name: SearchApplicationName::Firefox,
624 ..Default::default()
625 }
626 ),
627 "Should return true when the application name matches one in the environment when there are multiple"
628 );
629
630 assert!(
631 !matches_user_environment(
632 &crate::JSONVariantEnvironment {
633 applications: vec![
634 SearchApplicationName::FirefoxAndroid,
635 SearchApplicationName::Firefox
636 ],
637 ..Default::default()
638 },
639 &SearchUserEnvironment {
640 app_name: SearchApplicationName::FirefoxIos,
641 ..Default::default()
642 }
643 ),
644 "Should return false when the applications do not match the one in the environment"
645 );
646
647 assert!(
648 matches_user_environment(
649 &crate::JSONVariantEnvironment {
650 regions: vec!["fr".to_string()],
651 applications: vec![
652 SearchApplicationName::FirefoxAndroid,
653 SearchApplicationName::Firefox
654 ],
655 ..Default::default()
656 },
657 &SearchUserEnvironment {
658 locale: "fi".into(),
659 region: "fr".into(),
660 app_name: SearchApplicationName::Firefox,
661 ..Default::default()
662 }
663 ),
664 "Should return true when the application name matches the one in the environment"
665 );
666 }
667
668 #[test]
669 fn test_matches_user_environment_channel() {
670 assert!(
671 matches_user_environment(
672 &crate::JSONVariantEnvironment {
673 channels: vec![SearchUpdateChannel::Nightly],
674 ..Default::default()
675 },
676 &SearchUserEnvironment {
677 update_channel: SearchUpdateChannel::Nightly,
678 ..Default::default()
679 }
680 ),
681 "Should return true when the channel matches one in the environment"
682 );
683
684 assert!(
685 matches_user_environment(
686 &crate::JSONVariantEnvironment {
687 channels: vec![SearchUpdateChannel::Nightly, SearchUpdateChannel::Release],
688 ..Default::default()
689 },
690 &SearchUserEnvironment {
691 update_channel: SearchUpdateChannel::Release,
692 ..Default::default()
693 }
694 ),
695 "Should return true when the channel matches one in the environment when there are multiple"
696 );
697
698 assert!(
699 !matches_user_environment(
700 &crate::JSONVariantEnvironment {
701 channels: vec![SearchUpdateChannel::Nightly],
702 ..Default::default()
703 },
704 &SearchUserEnvironment {
705 locale: "fi".into(),
706 region: "fr".into(),
707 update_channel: SearchUpdateChannel::Default,
708 distribution_id: "distro-4".into(),
709 experiment: String::new(),
710 app_name: SearchApplicationName::Firefox,
711 version: String::new(),
712 device_type: SearchDeviceType::None,
713 }
714 ),
715 "Should return false when the channel does not match any in the environment"
716 );
717
718 assert!(
719 matches_user_environment(
720 &crate::JSONVariantEnvironment {
721 regions: vec!["fr".to_string()],
722 channels: vec![SearchUpdateChannel::Default],
723 ..Default::default()
724 },
725 &SearchUserEnvironment {
726 locale: "fi".into(),
727 region: "fr".into(),
728 update_channel: SearchUpdateChannel::Default,
729 ..Default::default()
730 }
731 ),
732 "Should return true when the channel and region matches the environment"
733 );
734 }
735
736 #[test]
737 fn test_matches_user_environment_experiment() {
738 assert!(
739 matches_user_environment(
740 &crate::JSONVariantEnvironment {
741 experiment: "warp-drive".to_string(),
742 ..Default::default()
743 },
744 &SearchUserEnvironment {
745 experiment: "warp-drive".to_string(),
746 ..Default::default()
747 }
748 ),
749 "Should return true when the experiment matches the one in the environment"
750 );
751
752 assert!(
753 !matches_user_environment(
754 &crate::JSONVariantEnvironment {
755 experiment: "warp-drive".to_string(),
756 ..Default::default()
757 },
758 &SearchUserEnvironment {
759 experiment: "cloak".to_string(),
760 ..Default::default()
761 }
762 ),
763 "Should return false when the experiment does not match the one in the environment"
764 );
765
766 assert!(
767 matches_user_environment(
768 &crate::JSONVariantEnvironment {
769 regions: vec!["fr".to_string()],
770 experiment: "warp-drive".to_string(),
771 ..Default::default()
772 },
773 &SearchUserEnvironment {
774 locale: "fi".into(),
775 region: "fr".into(),
776 experiment: "warp-drive".to_string(),
777 ..Default::default()
778 }
779 ),
780 "Should return true when the experiment and region matches the environment"
781 );
782 }
783
784 #[test]
785 fn test_matches_user_environment_versions() {
786 assert!(
787 !matches_user_environment(
788 &crate::JSONVariantEnvironment {
789 min_version: "43.0.0".to_string(),
790 max_version: "".to_string(),
791 ..Default::default()
792 },
793 &SearchUserEnvironment {
794 version: "42.0.0".to_string(),
795 ..Default::default()
796 },
797 ),
798 "Should return false when the version is below the minimum"
799 );
800 assert!(
801 matches_user_environment(
802 &crate::JSONVariantEnvironment {
803 min_version: "42.0.0".to_string(),
804 max_version: "".to_string(),
805 ..Default::default()
806 },
807 &SearchUserEnvironment {
808 version: "42.0.0".to_string(),
809 ..Default::default()
810 },
811 ),
812 "Should return true when the version is equal to the minimum"
813 );
814 assert!(
815 matches_user_environment(
816 &crate::JSONVariantEnvironment {
817 min_version: "41.0.0".to_string(),
818 max_version: "".to_string(),
819 ..Default::default()
820 },
821 &SearchUserEnvironment {
822 version: "42.0.0".to_string(),
823 ..Default::default()
824 },
825 ),
826 "Should return true when the version is above the minimum"
827 );
828
829 assert!(
830 matches_user_environment(
831 &crate::JSONVariantEnvironment {
832 min_version: "".to_string(),
833 max_version: "43.0.0".to_string(),
834 ..Default::default()
835 },
836 &SearchUserEnvironment {
837 version: "42.0.0".to_string(),
838 ..Default::default()
839 },
840 ),
841 "Should return true when the version is below the maximum"
842 );
843 assert!(
844 matches_user_environment(
845 &crate::JSONVariantEnvironment {
846 min_version: "".to_string(),
847 max_version: "42.0.0".to_string(),
848 ..Default::default()
849 },
850 &SearchUserEnvironment {
851 version: "42.0.0".to_string(),
852 ..Default::default()
853 },
854 ),
855 "Should return true when the version is equal to the maximum"
856 );
857 assert!(
858 !matches_user_environment(
859 &crate::JSONVariantEnvironment {
860 min_version: "".to_string(),
861 max_version: "41.0.0".to_string(),
862 ..Default::default()
863 },
864 &SearchUserEnvironment {
865 version: "42.0.0".to_string(),
866 ..Default::default()
867 },
868 ),
869 "Should return false when the version is above the maximum"
870 );
871
872 assert!(
873 !matches_user_environment(
874 &crate::JSONVariantEnvironment {
875 min_version: "41.0.0".to_string(),
876 max_version: "43.0.0".to_string(),
877 ..Default::default()
878 },
879 &SearchUserEnvironment {
880 version: "2.0.0".to_string(),
881 ..Default::default()
882 },
883 ),
884 "Should return false when the version is below the minimum and both are specified"
885 );
886 assert!(
887 matches_user_environment(
888 &crate::JSONVariantEnvironment {
889 min_version: "41.0.0".to_string(),
890 max_version: "43.0.0".to_string(),
891 ..Default::default()
892 },
893 &SearchUserEnvironment {
894 version: "41.0.0".to_string(),
895 ..Default::default()
896 },
897 ),
898 "Should return true when the version is equal to the minimum and both are specified"
899 );
900 assert!(
901 matches_user_environment(
902 &crate::JSONVariantEnvironment {
903 min_version: "41.0.0".to_string(),
904 max_version: "43.0.0".to_string(),
905 ..Default::default()
906 },
907 &SearchUserEnvironment {
908 version: "42.0.0".to_string(),
909 ..Default::default()
910 },
911 ),
912 "Should return true when the version is between the minimum and maximum"
913 );
914 assert!(
915 matches_user_environment(
916 &crate::JSONVariantEnvironment {
917 min_version: "41.0.0".to_string(),
918 max_version: "43.0.0".to_string(),
919 ..Default::default()
920 },
921 &SearchUserEnvironment {
922 version: "43.0.0".to_string(),
923 ..Default::default()
924 },
925 ),
926 "Should return true when the version is equal to the maximum and both are specified"
927 );
928 assert!(
929 !matches_user_environment(
930 &crate::JSONVariantEnvironment {
931 min_version: "41.0.0".to_string(),
932 max_version: "43.0.0".to_string(),
933 ..Default::default()
934 },
935 &SearchUserEnvironment {
936 version: "44.0.0".to_string(),
937 ..Default::default()
938 },
939 ),
940 "Should return false when the version is above the maximum and both are specified"
941 );
942 }
943
944 #[test]
945 fn test_matches_user_environment_device_type() {
946 assert!(
947 matches_user_environment(
948 &crate::JSONVariantEnvironment {
949 device_type: vec![SearchDeviceType::None],
950 ..Default::default()
951 },
952 &SearchUserEnvironment {
953 device_type: SearchDeviceType::None,
954 ..Default::default()
955 }
956 ),
957 "Should return true when the device type matches one in the environment"
958 );
959
960 assert!(
961 matches_user_environment(
962 &crate::JSONVariantEnvironment {
963 device_type: vec![SearchDeviceType::Smartphone, SearchDeviceType::Tablet],
964 ..Default::default()
965 },
966 &SearchUserEnvironment {
967 device_type: SearchDeviceType::Tablet,
968 ..Default::default()
969 }
970 ),
971 "Should return true when the device type matches one in the environment when there are multiple"
972 );
973
974 assert!(
975 !matches_user_environment(
976 &crate::JSONVariantEnvironment {
977 device_type: vec![SearchDeviceType::Smartphone],
978 ..Default::default()
979 },
980 &SearchUserEnvironment {
981 device_type: SearchDeviceType::None,
982 ..Default::default()
983 }
984 ),
985 "Should return false when the device type does not match any in the environment"
986 );
987
988 assert!(
989 matches_user_environment(
990 &crate::JSONVariantEnvironment {
991 regions: vec!["fr".to_string()],
992 device_type: vec![SearchDeviceType::Tablet],
993 ..Default::default()
994 },
995 &SearchUserEnvironment {
996 locale: "fi".into(),
997 region: "fr".into(),
998 device_type: SearchDeviceType::Tablet,
999 ..Default::default()
1000 }
1001 ),
1002 "Should return true when the device type and region matches the environment"
1003 );
1004 }
1005}