1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use crate::PackagePath;
use fuchsia_url::test::{random_package_name, random_package_variant};
use proptest::prelude::*;

#[cfg(test)]
use {
    crate::{MetaPackage, PackageBuildManifest},
    fuchsia_url::test::random_resource_path,
};

#[cfg(test)]
prop_compose! {
    /// Returns a random valid host path character. Host platforms have different requirements on
    /// what are valid path characters. On linux, it can be any character except for '/' and null,
    /// whereas APFS also requires that any unicode codepoints must be defined in Unicode 9.0.
    /// Furthermore, some filesystems are case insensitive, and so a file named "foo" and "Foo"
    /// conflict.
    ///
    /// For our testing purposes, we don't really care about testing what paths an operating system
    /// supports, so we'll just use randomly generate lowercase alphanumeric characters.
    fn random_host_path_char()(c in "[a-z0-9]") -> String {
        c
    }
}

#[cfg(test)]
prop_compose! {
    fn random_host_path_component
        (min: usize, max: usize)
        (s in prop::collection::vec(random_host_path_char(), min..max)) -> String {
            s.join("")
        }
}

#[cfg(test)]
prop_compose! {
    fn random_host_path
        (min: usize, max: usize)
        (s in prop::collection::vec(random_host_path_component(1, 4), min..max))
         -> String
    {
        s.join("/")
    }
}

#[cfg(test)]
prop_compose! {
    pub(crate) fn random_external_resource_path()
        (s in random_resource_path(1, 4)
         .prop_filter(
             "External package contents cannot be in the 'meta/' directory",
             |s| !s.starts_with("meta/"))
        ) -> String
    {
        s
    }
}

#[cfg(test)]
prop_compose! {
    pub(crate) fn random_far_resource_path()
        (s in random_resource_path(1, 4)) -> String
    {
        format!("meta/{s}")
    }
}

#[cfg(test)]
prop_compose! {
    pub(crate) fn random_hash()(s: [u8; 32]) -> fuchsia_merkle::Hash {
        s.into()
    }
}

#[cfg(test)]
prop_compose! {
    pub(crate) fn random_merkle_hex()(s in "[[:xdigit:]]{64}") -> String {
        s
    }
}

#[cfg(test)]
prop_compose! {
    fn random_creation_manifest_result()
        (external_content in prop::collection::btree_map(
            random_external_resource_path(), random_host_path(1, 2), 1..4),
         mut far_content in prop::collection::btree_map(
             random_far_resource_path(), random_host_path(1, 2), 1..4),)
         -> Result<PackageBuildManifest, crate::errors::PackageBuildManifestError>
    {
        far_content.insert("meta/package".to_string(), "meta/package".to_string());
        PackageBuildManifest::from_external_and_far_contents(
            external_content, far_content)
    }
}

#[cfg(test)]
prop_compose! {
    pub(crate) fn random_creation_manifest()
        (manifest_result in random_creation_manifest_result().prop_filter(
            "path combinations cannot have file/directory collisions, like ['foo', 'foo/bar']",
            |r| r.is_ok()
        ))
         -> PackageBuildManifest
    {
        manifest_result.unwrap()
    }
}

#[cfg(test)]
prop_compose! {
    pub(crate) fn random_meta_package()(name in random_package_name()) -> MetaPackage {
        MetaPackage::from_name_and_variant_zero(name)
    }
}

prop_compose! {
    pub fn random_package_path()(
        name in random_package_name(),
        variant in random_package_variant()
    ) -> PackagePath {
        PackagePath::from_name_and_variant(name, variant)
    }
}