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
129
130
// 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,
    fuchsia_url::test::{random_package_name, random_package_variant},
    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)
    }
}