1use anyhow::Error;
6
7pub struct Cache {
9 _pkg_cache_proxy: fidl_fuchsia_pkg::PackageCacheProxy,
10}
11
12impl Cache {
13 pub fn new_with_proxies(
16 pkg_cache_proxy: fidl_fuchsia_pkg::PackageCacheProxy,
17 ) -> Result<Self, Error> {
18 Ok(Self { _pkg_cache_proxy: pkg_cache_proxy })
19 }
20
21 pub fn new() -> Result<Self, Error> {
25 Ok(Self {
26 _pkg_cache_proxy: fuchsia_component::client::connect_to_protocol::<
27 fidl_fuchsia_pkg::PackageCacheMarker,
28 >()?,
29 })
30 }
31
32 #[cfg(test)]
34 pub fn package_cache_proxy(&self) -> Result<fidl_fuchsia_pkg::PackageCacheProxy, Error> {
35 Ok(self._pkg_cache_proxy.clone())
36 }
37}
38
39#[cfg(test)]
40pub(crate) mod for_tests {
41 use super::*;
42 use blobfs_ramdisk::BlobfsRamdisk;
43 use fidl::endpoints::{ServerEnd, SynchronousProxy};
44 use fuchsia_component_test::{
45 Capability, ChildOptions, ChildRef, RealmBuilder, RealmInstance, Ref, Route,
46 };
47 use futures::prelude::*;
48 use std::sync::Arc;
49 use {
50 fidl_fuchsia_fxfs as ffxfs, fidl_fuchsia_io as fio, fidl_fuchsia_metrics as fmetrics,
51 fuchsia_async as fasync,
52 };
53
54 pub struct CacheForTest {
55 pub blobfs: blobfs_ramdisk::BlobfsRamdisk,
56 pub cache: Arc<Cache>,
57 }
58
59 impl CacheForTest {
60 pub async fn realm_setup(
61 realm_builder: &RealmBuilder,
62 blobfs: &BlobfsRamdisk,
63 ) -> Result<ChildRef, Error> {
64 let blobfs_proxy = blobfs.root_dir_proxy().expect("getting root dir proxy");
65 let svc_dir = blobfs.svc_dir().expect("getting service dir proxy");
66
67 let local_mocks = realm_builder
68 .add_local_child(
69 "pkg_cache_service_reflector",
70 move |handles| {
71 let mut fs = fuchsia_component::server::ServiceFs::new();
72 let (creator_dir, server_end) =
73 fidl::endpoints::create_sync_proxy::<fio::DirectoryMarker>();
74 svc_dir
75 .open(
76 ".",
77 fio::PERM_READABLE,
78 &fio::Options::default(),
79 server_end.into_channel(),
80 )
81 .unwrap();
82 let (reader_dir, server_end) =
83 fidl::endpoints::create_sync_proxy::<fio::DirectoryMarker>();
84 svc_dir
85 .open(
86 ".",
87 fio::PERM_READABLE,
88 &fio::Options::default(),
89 server_end.into_channel(),
90 )
91 .unwrap();
92 fs.dir("svc")
94 .add_fidl_service(move |stream| {
95 fasync::Task::spawn(
96 Arc::new(mock_metrics::MockMetricEventLoggerFactory::new())
97 .run_logger_factory(stream),
98 )
99 .detach()
100 })
101 .add_service_connector(
102 move |server_end: ServerEnd<ffxfs::BlobCreatorMarker>| {
103 fdio::service_connect_at(
104 creator_dir.as_channel(),
105 "fuchsia.fxfs.BlobCreator",
106 server_end.into_channel(),
107 )
108 .unwrap();
109 },
110 )
111 .add_service_connector(
112 move |server_end: ServerEnd<ffxfs::BlobReaderMarker>| {
113 fdio::service_connect_at(
114 reader_dir.as_channel(),
115 "fuchsia.fxfs.BlobReader",
116 server_end.into_channel(),
117 )
118 .unwrap();
119 },
120 );
121 fs.add_remote("blob", Clone::clone(&blobfs_proxy));
122 async move {
123 fs.serve_connection(handles.outgoing_dir).unwrap();
124 let () = fs.collect().await;
125 Ok(())
126 }
127 .boxed()
128 },
129 ChildOptions::new(),
130 )
131 .await
132 .unwrap();
133
134 let pkg_cache = realm_builder
135 .add_child("pkg_cache", "#meta/pkg-cache.cm", ChildOptions::new())
136 .await
137 .unwrap();
138
139 realm_builder
140 .add_capability(cm_rust::CapabilityDecl::Config(cm_rust::ConfigurationDecl {
141 name: "fuchsia.zircon.system.pkgfs.cmd".parse().unwrap(),
142 value: "test".into(),
143 }))
144 .await
145 .unwrap();
146 realm_builder
147 .add_route(
148 Route::new()
149 .capability(Capability::configuration("fuchsia.zircon.system.pkgfs.cmd"))
150 .from(Ref::self_())
151 .to(&pkg_cache),
152 )
153 .await
154 .unwrap();
155 let pkg_cache_config = realm_builder
156 .add_child("pkg_cache_config", "#meta/pkg-cache-config.cm", ChildOptions::new())
157 .await
158 .unwrap();
159 realm_builder
160 .add_route(
161 Route::new()
162 .capability(Capability::configuration(
163 "fuchsia.pkgcache.AllPackagesExecutable",
164 ))
165 .capability(Capability::configuration("fuchsia.pkgcache.UseSystemImage"))
166 .capability(Capability::configuration(
167 "fuchsia.pkgcache.EnableUpgradablePackages",
168 ))
169 .from(&pkg_cache_config)
170 .to(&pkg_cache),
171 )
172 .await
173 .unwrap();
174 let system_update_committer = realm_builder
175 .add_child(
176 "system-update-committer",
177 "#meta/fake-system-update-committer.cm",
178 ChildOptions::new(),
179 )
180 .await
181 .unwrap();
182
183 realm_builder
184 .add_route(
185 Route::new()
186 .capability(
187 Capability::directory("blob-exec")
188 .path("/blob")
189 .rights(fio::RW_STAR_DIR | fio::Operations::EXECUTE),
190 )
191 .from(&local_mocks)
192 .to(&pkg_cache),
193 )
194 .await
195 .unwrap();
196
197 realm_builder
198 .add_route(
199 Route::new()
200 .capability(Capability::protocol_by_name("fuchsia.logger.LogSink"))
201 .from(Ref::parent())
202 .to(&pkg_cache),
203 )
204 .await
205 .unwrap();
206
207 realm_builder
208 .add_route(
209 Route::new()
210 .capability(Capability::protocol_by_name("fuchsia.fxfs.BlobCreator"))
211 .capability(Capability::protocol_by_name("fuchsia.fxfs.BlobReader"))
212 .from(&local_mocks)
213 .to(&pkg_cache),
214 )
215 .await
216 .unwrap();
217
218 realm_builder
219 .add_route(
220 Route::new()
221 .capability(Capability::protocol_by_name("fuchsia.pkg.PackageCache"))
222 .capability(Capability::protocol_by_name("fuchsia.pkg.RetainedPackages"))
223 .capability(Capability::protocol_by_name(
224 "fuchsia.pkg.garbagecollector.Manager",
225 ))
226 .from(&pkg_cache)
227 .to(Ref::parent()),
228 )
229 .await
230 .unwrap();
231
232 realm_builder
233 .add_route(
234 Route::new()
235 .capability(Capability::protocol_by_name(
236 "fuchsia.update.CommitStatusProvider",
237 ))
238 .from(&system_update_committer)
239 .to(&pkg_cache),
240 )
241 .await
242 .unwrap();
243
244 realm_builder
245 .add_route(
246 Route::new()
247 .capability(
248 Capability::protocol::<fmetrics::MetricEventLoggerFactoryMarker>(),
249 )
250 .from(&local_mocks)
251 .to(&pkg_cache),
252 )
253 .await
254 .unwrap();
255 Ok(pkg_cache)
256 }
257
258 pub async fn new(
259 realm_instance: &RealmInstance,
260 blobfs: BlobfsRamdisk,
261 ) -> Result<Self, Error> {
262 let pkg_cache_proxy = realm_instance
263 .root
264 .connect_to_protocol_at_exposed_dir()
265 .expect("connect to pkg cache");
266
267 let cache = Cache::new_with_proxies(pkg_cache_proxy).unwrap();
268
269 Ok(CacheForTest { blobfs, cache: Arc::new(cache) })
270 }
271 }
272}
273
274#[cfg(test)]
275mod tests {
276 use super::for_tests::CacheForTest;
277 use fuchsia_async as fasync;
278 use fuchsia_component_test::RealmBuilder;
279
280 #[fasync::run_singlethreaded(test)]
281 pub async fn test_cache_handles_sync() {
282 let realm_builder = RealmBuilder::new().await.unwrap();
283 let blobfs = blobfs_ramdisk::BlobfsRamdisk::start().await.expect("starting blobfs");
284
285 let _cache_ref =
286 CacheForTest::realm_setup(&realm_builder, &blobfs).await.expect("setting up realm");
287 let realm_instance = realm_builder.build().await.unwrap();
288 let cache = CacheForTest::new(&realm_instance, blobfs).await.expect("launching cache");
289 let proxy = cache.cache.package_cache_proxy().unwrap();
290
291 assert_eq!(proxy.sync().await.unwrap(), Ok(()));
292 }
293}