diff --git a/src/addon_transport/http_transport/http_transport.rs b/src/addon_transport/http_transport/http_transport.rs index 80e54e113..79d6ae50f 100644 --- a/src/addon_transport/http_transport/http_transport.rs +++ b/src/addon_transport/http_transport/http_transport.rs @@ -2,21 +2,20 @@ use crate::addon_transport::http_transport::legacy::AddonLegacyTransport; use crate::addon_transport::AddonTransport; use crate::constants::{ADDON_LEGACY_PATH, ADDON_MANIFEST_PATH, URI_COMPONENT_ENCODE_SET}; use crate::runtime::{Env, EnvError, EnvFutureExt, TryEnvFuture}; -use crate::types::addon::{Manifest, ResourcePath, ResourceResponse}; +use crate::types::addon::{Manifest, ResourcePath, ResourceResponse, TransportUrl}; use crate::types::query_params_encode; use futures::future; use http::Request; use percent_encoding::utf8_percent_encode; use std::marker::PhantomData; -use url::Url; pub struct AddonHTTPTransport { - transport_url: Url, + transport_url: TransportUrl, env: PhantomData, } impl AddonHTTPTransport { - pub fn new(transport_url: Url) -> Self { + pub fn new(transport_url: TransportUrl) -> Self { AddonHTTPTransport { transport_url, env: PhantomData, diff --git a/src/constants.rs b/src/constants.rs index 31eb0aa8a..720a4abeb 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -1,4 +1,4 @@ -use crate::types::addon::{Descriptor, ExtraProp, OptionsLimit}; +use crate::types::addon::{Descriptor, ExtraProp, OptionsLimit, TransportUrl}; use lazy_static::lazy_static; use percent_encoding::{AsciiSet, NON_ALPHANUMERIC}; use std::collections::HashMap; @@ -57,7 +57,7 @@ lazy_static! { .expect("CINEMETA_URL parse failed"); /// Manifest URL for Cinemeta V3 - pub static ref CINEMETA_URL: Url = Url::parse("https://v3-cinemeta.strem.io/manifest.json") + pub static ref CINEMETA_URL: TransportUrl = TransportUrl::parse("https://v3-cinemeta.strem.io/manifest.json") .expect("CINEMETA_URL parse failed"); pub static ref API_URL: Url = Url::parse("https://api.strem.io").expect("API_URL parse failed"); pub static ref LINK_API_URL: Url = diff --git a/src/models/addon_details.rs b/src/models/addon_details.rs index 98deb0e4f..4f27517b0 100644 --- a/src/models/addon_details.rs +++ b/src/models/addon_details.rs @@ -1,16 +1,24 @@ -use crate::models::common::{descriptor_update, eq_update, DescriptorAction, DescriptorLoadable}; -use crate::models::ctx::Ctx; -use crate::runtime::msg::{Action, ActionLoad, Internal, Msg}; -use crate::runtime::{Effects, Env, UpdateWithCtx}; -use crate::types::addon::Descriptor; -use crate::types::profile::Profile; use serde::{Deserialize, Serialize}; -use url::Url; + +use crate::{ + models::{ + common::{descriptor_update, eq_update, DescriptorAction, DescriptorLoadable}, + ctx::Ctx, + }, + runtime::{ + msg::{Action, ActionLoad, Internal, Msg}, + Effects, Env, UpdateWithCtx, + }, + types::{ + addon::{Descriptor, TransportUrl}, + profile::Profile, + }, +}; #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] #[serde(rename_all = "camelCase")] pub struct Selected { - pub transport_url: Url, + pub transport_url: TransportUrl, } #[derive(Default, Clone, Serialize)] diff --git a/src/models/common/descriptor_loadable.rs b/src/models/common/descriptor_loadable.rs index 093e1649a..ee91af7cb 100644 --- a/src/models/common/descriptor_loadable.rs +++ b/src/models/common/descriptor_loadable.rs @@ -2,15 +2,15 @@ use crate::constants::OFFICIAL_ADDONS; use crate::models::common::Loadable; use crate::runtime::msg::{Internal, Msg}; use crate::runtime::{EffectFuture, Effects, Env, EnvError, EnvFutureExt}; -use crate::types::addon::{Descriptor, Manifest}; +use crate::types::addon::{Descriptor, Manifest, TransportUrl}; + use futures::FutureExt; use serde::Serialize; -use url::Url; /// Fetching addons #[derive(PartialEq, Serialize, Clone, Debug)] pub struct DescriptorLoadable { - pub transport_url: Url, + pub transport_url: TransportUrl, pub content: Loadable, } @@ -18,11 +18,11 @@ pub enum DescriptorAction<'a> { /// Requests the addon [`Descriptor`] DescriptorRequested { /// The transport_url is unique for every addon. - transport_url: &'a Url, + transport_url: &'a TransportUrl, }, /// Loads the manifest for the addon of the [`Descriptor`] ManifestRequestResult { - transport_url: &'a Url, + transport_url: &'a TransportUrl, result: &'a Result, }, } diff --git a/src/models/ctx/update_trakt_addon.rs b/src/models/ctx/update_trakt_addon.rs index 3001a2948..fd5e80bb7 100644 --- a/src/models/ctx/update_trakt_addon.rs +++ b/src/models/ctx/update_trakt_addon.rs @@ -1,3 +1,5 @@ +use percent_encoding::utf8_percent_encode; + use crate::constants::URI_COMPONENT_ENCODE_SET; use crate::models::common::{ descriptor_update, eq_update, DescriptorAction, DescriptorLoadable, Loadable, @@ -5,9 +7,8 @@ use crate::models::common::{ use crate::models::ctx::{CtxError, CtxStatus, OtherError}; use crate::runtime::msg::{Action, ActionCtx, Event, Internal, Msg}; use crate::runtime::{Effects, Env}; +use crate::types::addon::TransportUrl; use crate::types::profile::Profile; -use percent_encoding::utf8_percent_encode; -use url::Url; pub fn update_trakt_addon( trakt_addon: &mut Option, @@ -25,7 +26,7 @@ pub fn update_trakt_addon( Some(uid) => descriptor_update::( trakt_addon, DescriptorAction::DescriptorRequested { - transport_url: &Url::parse(&format!( + transport_url: &TransportUrl::parse(&format!( "https://www.strem.io/trakt/addon/{}/manifest.json", utf8_percent_encode(&uid, URI_COMPONENT_ENCODE_SET) )) diff --git a/src/models/player.rs b/src/models/player.rs index 3cbb92b67..66ff35f3f 100644 --- a/src/models/player.rs +++ b/src/models/player.rs @@ -817,7 +817,7 @@ mod test { constants::YOUTUBE_ADDON_ID_PREFIX, models::common::{Loadable, ResourceLoadable}, types::{ - addon::{ResourcePath, ResourceRequest}, + addon::{ResourcePath, ResourceRequest, TransportUrl}, resource::{SeriesInfo, Stream, Video}, }, unit_tests::TestEnv, @@ -833,7 +833,7 @@ mod test { let next_youtube_stream = Stream::youtube(&next_youtube_1234).unwrap(); let youtube_base = "https://youtube.com" - .parse::() + .parse::() .expect("Valid youtube url"); let next_streams = ResourceLoadable { request: ResourceRequest { diff --git a/src/runtime/env.rs b/src/runtime/env.rs index 9bb72566e..d77e87cc7 100644 --- a/src/runtime/env.rs +++ b/src/runtime/env.rs @@ -1,3 +1,11 @@ +use std::fmt; + +use chrono::{DateTime, Utc}; +use futures::{future, Future, TryFutureExt}; +use http::Request; +use serde::ser::SerializeStruct; +use serde::{Deserialize, Serialize, Serializer}; + use crate::addon_transport::{AddonHTTPTransport, AddonTransport, UnsupportedTransport}; use crate::constants::{ LIBRARY_RECENT_STORAGE_KEY, LIBRARY_STORAGE_KEY, PROFILE_STORAGE_KEY, SCHEMA_VERSION, @@ -5,13 +13,7 @@ use crate::constants::{ }; use crate::models::ctx::Ctx; use crate::models::streaming_server::StreamingServer; -use chrono::{DateTime, Utc}; -use futures::{future, Future, TryFutureExt}; -use http::Request; -use serde::ser::SerializeStruct; -use serde::{Deserialize, Serialize, Serializer}; -use std::fmt; -use url::Url; +use crate::types::addon::TransportUrl; pub use conditional_types::{ConditionalSend, EnvFuture, EnvFutureExt}; @@ -156,13 +158,13 @@ pub trait Env { ) -> serde_json::Value; #[cfg(debug_assertions)] fn log(message: String); - fn addon_transport(transport_url: &Url) -> Box + fn addon_transport(transport_url: &TransportUrl) -> Box where Self: Sized + 'static, { match transport_url.scheme() { "http" | "https" => Box::new(AddonHTTPTransport::::new(transport_url.to_owned())), - _ => Box::new(UnsupportedTransport::new(transport_url.to_owned())), + _ => Box::new(UnsupportedTransport::new(transport_url.into())), } } fn migrate_storage_schema() -> TryEnvFuture<()> diff --git a/src/runtime/msg/event.rs b/src/runtime/msg/event.rs index 210228a53..7ac0027e8 100644 --- a/src/runtime/msg/event.rs +++ b/src/runtime/msg/event.rs @@ -1,11 +1,16 @@ -use crate::models::ctx::CtxError; -use crate::models::player::AnalyticsContext as PlayerAnalyticsContext; -use crate::types::api::AuthRequest; -use crate::types::library::LibraryItemId; -use crate::types::profile::{AuthKey, Settings, UID}; use serde::Serialize; use url::Url; +use crate::{ + models::{ctx::CtxError, player::AnalyticsContext as PlayerAnalyticsContext}, + types::{ + addon::TransportUrl, + api::AuthRequest, + library::LibraryItemId, + profile::{AuthKey, Settings, UID}, + }, +}; + /// /// Those messages are meant to be dispatched by the `stremio-core` crate and /// handled by the users of the `stremio-core` crate and by the `stremio-core` @@ -50,10 +55,10 @@ pub enum Event { uid: UID, }, AddonsPulledFromAPI { - transport_urls: Vec, + transport_urls: Vec, }, AddonsPushedToAPI { - transport_urls: Vec, + transport_urls: Vec, }, LibrarySyncWithAPIPlanned { uid: UID, @@ -81,15 +86,15 @@ pub enum Event { uid: UID, }, AddonInstalled { - transport_url: Url, + transport_url: TransportUrl, id: String, }, AddonUpgraded { - transport_url: Url, + transport_url: TransportUrl, id: String, }, AddonUninstalled { - transport_url: Url, + transport_url: TransportUrl, id: String, }, SettingsUpdated { diff --git a/src/runtime/msg/internal.rs b/src/runtime/msg/internal.rs index 6173f7d9d..67109ec2b 100644 --- a/src/runtime/msg/internal.rs +++ b/src/runtime/msg/internal.rs @@ -7,7 +7,7 @@ use crate::models::streaming_server::{ PlaybackDevice, Settings as StreamingServerSettings, StatisticsRequest, }; use crate::runtime::EnvError; -use crate::types::addon::{Descriptor, Manifest, ResourceRequest, ResourceResponse}; +use crate::types::addon::{Descriptor, Manifest, ResourceRequest, ResourceResponse, TransportUrl}; use crate::types::api::{ APIRequest, AuthRequest, DataExportResponse, DatastoreRequest, LinkCodeResponse, LinkDataResponse, @@ -51,7 +51,7 @@ pub enum Internal { stream: Stream, meta_id: Option, video_id: Option, - transport_url: Option, + transport_url: Option, }, /// Dispatched when library item needs to be updated in the memory, storage and API. UpdateLibraryItem(LibraryItem), @@ -86,7 +86,7 @@ pub enum Internal { /// Result for fetching resource from addons. ResourceRequestResult(ResourceRequest, Box>), /// Result for fetching manifest from addon. - ManifestRequestResult(Url, Result), + ManifestRequestResult(TransportUrl, Result), /// TODO: write some obvious comment about what it is NotificationsRequestResult(ResourceRequest, Box>), /// Result for requesting a `dataExport` of user data. diff --git a/src/types/addon/descriptor.rs b/src/types/addon/descriptor.rs index fc6618677..146457a88 100644 --- a/src/types/addon/descriptor.rs +++ b/src/types/addon/descriptor.rs @@ -1,13 +1,12 @@ -use crate::types::addon::{Manifest, ManifestPreview}; +use crate::types::addon::{Manifest, ManifestPreview, TransportUrl}; use serde::{Deserialize, Serialize}; -use url::Url; /// Addon descriptor #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] #[serde(rename_all = "camelCase")] pub struct Descriptor { pub manifest: Manifest, - pub transport_url: Url, + pub transport_url: TransportUrl, #[serde(default)] pub flags: DescriptorFlags, } @@ -16,7 +15,7 @@ pub struct Descriptor { #[serde(rename_all = "camelCase")] pub struct DescriptorPreview { pub manifest: ManifestPreview, - pub transport_url: Url, + pub transport_url: TransportUrl, } #[derive(Default, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] diff --git a/src/types/addon/mod.rs b/src/types/addon/mod.rs deleted file mode 100644 index 57b43dff5..000000000 --- a/src/types/addon/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -mod descriptor; -pub use descriptor::*; - -mod manifest; -pub use manifest::*; - -mod request; -pub use request::*; - -mod response; -pub use response::*; diff --git a/src/types/addon/transport_url.rs b/src/types/addon/transport_url.rs new file mode 100644 index 000000000..a0f3548df --- /dev/null +++ b/src/types/addon/transport_url.rs @@ -0,0 +1,189 @@ +use std::{ops, str::FromStr}; + +use serde::{Deserialize, Serialize}; +use thiserror::Error; +use url::Url; + +#[derive(Debug, Error, PartialEq, Eq)] +pub enum Error { + /// Only stremio:// and https:// are allowed + #[error("Url scheme is not supported, only stremio:// and https:// are allowed.")] + UnsupportedScheme, + #[error("Invalid Url")] + ParsingUrl(#[from] url::ParseError), +} + +/// An Addon transport Url `stremio://example_addon.com` or `https://example_addon.com` +/// +/// When deserializing the url: +/// - Should start with either `stremio://` or `https://` +/// +/// Optionally it can end with `manifest.json` for SDK Addons. +/// +#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)] +#[serde(try_from = "Url", into = "Url")] +pub struct TransportUrl { + url: Url, + pub has_manifest: bool, +} + +/// The manifest.json filename that we define the TransportUrl with. +const MANIFEST: &str = "manifest.json"; + +impl TransportUrl { + /// + /// # Examples + /// + /// ## Parsing + /// + /// ``` + /// let with_manifest = TransportUrl::parse("https://v3-cinemeta.strem.io/manifest.json").expect("Cinemeta url parse failed"); + /// assert!(with_manifest.has_manifest); + /// + /// let no_manifest = TransportUrl::parse("https://v3-cinemeta.strem.io").expect("Cinemeta url parse failed"); + /// assert!(!no_manifest.has_manifest); + /// + ///``` + /// + pub fn new(addon_url: Url) -> Self { + Self { + has_manifest: has_manifest(&addon_url), + url: addon_url, + } + } + + pub fn parse(input: &str) -> Result { + input.parse() + } +} + +impl From for Url { + fn from(transport_url: TransportUrl) -> Url { + transport_url.url + } +} + +impl From<&TransportUrl> for Url { + fn from(transport_url: &TransportUrl) -> Url { + transport_url.url.to_owned() + } +} + +impl TryFrom for TransportUrl { + type Error = Error; + + fn try_from(url: Url) -> Result { + let sanitized_url = match url.scheme() { + "https" | "http" => url, + // replace stremio:// with https:// + "stremio" => url + .as_str() + .replacen("stremio", "https", 1) + .parse() + .expect("Should never fail"), + _ => return Err(Error::UnsupportedScheme), + }; + + let with_manifest = sanitized_url.path().ends_with("manifest.json"); + + Ok(Self { + url: sanitized_url, + has_manifest: with_manifest, + }) + } +} + +impl ops::Deref for TransportUrl { + type Target = Url; + + fn deref(&self) -> &Self::Target { + &self.url + } +} + +impl FromStr for TransportUrl { + type Err = Error; + + fn from_str(s: &str) -> Result { + let url = s.parse::()?; + + Self::try_from(url) + } +} +fn has_manifest(url: &Url) -> bool { + url.path().ends_with(MANIFEST) +} + +#[cfg(test)] +mod test { + use url::Url; + + use super::{Error, TransportUrl}; + + #[test] + fn test_deserialization_of_transport_url() { + // stremio:// protocol w/ manifest.json + { + let url = "stremio://addon_url.com/manifest.json" + .parse::() + .expect("Should parse"); + let expected_url = "https://addon_url.com/manifest.json" + .parse::() + .expect("Should parse"); + + let transport_url = TransportUrl::try_from(url).expect("Should convert"); + assert_eq!(expected_url, transport_url.url); + assert!(transport_url.has_manifest); + } + + // stremio:// protocol w/out manifest.json + { + let url = "stremio://addon_url.com" + .parse::() + .expect("Should parse"); + + let transport_url = TransportUrl::try_from(url).expect("Should parse"); + assert!(!transport_url.has_manifest); + } + + // https:// protocol w/ manifest.json + { + let url = "https://addon_url.com/manifest.json" + .parse::() + .expect("Should parse"); + + let transport_url = TransportUrl::try_from(url.clone()).expect("Should convert"); + assert_eq!(url, transport_url.url); + assert!(transport_url.has_manifest); + } + + // https:// protocol w/out manifest.json + { + let url = "https://addon_url.com" + .parse::() + .expect("Should parse"); + + let transport_url = TransportUrl::try_from(url).expect("Should parse"); + assert!(!transport_url.has_manifest); + } + + // http:// protocol w/ manifest.json + { + let url = "http://addon_url.com/manifest.json" + .parse::() + .expect("Should parse"); + + let transport_url = TransportUrl::try_from(url.clone()).expect("Should convert"); + assert_eq!(url, transport_url.url); + assert!(transport_url.has_manifest); + } + + // https:// protocol w/out manifest.json + { + let url = "http://addon_url.com".parse::().expect("Should parse"); + + let transport_url = TransportUrl::try_from(url).expect("Should parse"); + assert!(!transport_url.has_manifest) + } + } +} diff --git a/src/types/mod.rs b/src/types/mod.rs index 721e1707d..200ae4467 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -1,4 +1,19 @@ -pub mod addon; +pub mod addon { + mod descriptor; + pub use descriptor::*; + + mod manifest; + pub use manifest::*; + + mod request; + pub use request::*; + + mod response; + pub use response::*; + + mod transport_url; + pub use transport_url::*; +} pub mod api; pub mod library; pub mod notifications; diff --git a/src/types/profile/profile.rs b/src/types/profile/profile.rs index 7767fd0de..3e7cff382 100644 --- a/src/types/profile/profile.rs +++ b/src/types/profile/profile.rs @@ -54,6 +54,6 @@ impl UniqueVecAdapter for DescriptorUniqueVecAdapter { type Input = Descriptor; type Output = Url; fn hash(descriptor: &Descriptor) -> Url { - descriptor.transport_url.to_owned() + descriptor.transport_url.to_owned().into() } } diff --git a/src/types/streams/streams_item.rs b/src/types/streams/streams_item.rs index a1597ad3e..37c190d19 100644 --- a/src/types/streams/streams_item.rs +++ b/src/types/streams/streams_item.rs @@ -1,4 +1,4 @@ -use crate::types::resource::Stream; +use crate::types::{addon::TransportUrl, resource::Stream}; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use serde_with::serde_as; @@ -11,7 +11,7 @@ pub struct StreamsItem { pub stream: Stream, pub meta_id: String, pub video_id: String, - pub transport_url: Url, + pub transport_url: TransportUrl, /// Modification time #[serde(rename = "_mtime")] pub mtime: DateTime, diff --git a/src/unit_tests/catalog_with_filters/load_action.rs b/src/unit_tests/catalog_with_filters/load_action.rs index 6dea8fc19..f22533578 100644 --- a/src/unit_tests/catalog_with_filters/load_action.rs +++ b/src/unit_tests/catalog_with_filters/load_action.rs @@ -1,9 +1,19 @@ +use std::any::Any; +use std::sync::{Arc, RwLock}; + +use assert_matches::assert_matches; +use enclose::enclose; +use futures::future; +use stremio_derive::Model; + use crate::models::catalog_with_filters::{CatalogWithFilters, Selected}; use crate::models::common::{Loadable, ResourceLoadable}; use crate::models::ctx::Ctx; use crate::runtime::msg::{Action, ActionLoad}; use crate::runtime::{EnvFutureExt, Runtime, RuntimeAction, RuntimeEvent, TryEnvFuture}; -use crate::types::addon::{ExtraValue, ResourcePath, ResourceRequest, ResourceResponse}; +use crate::types::addon::{ + ExtraValue, ResourcePath, ResourceRequest, ResourceResponse, TransportUrl, +}; use crate::types::library::LibraryBucket; use crate::types::notifications::NotificationsBucket; use crate::types::profile::Profile; @@ -12,13 +22,6 @@ use crate::types::streams::StreamsBucket; use crate::unit_tests::{ default_fetch_handler, Request, TestEnv, EVENTS, FETCH_HANDLER, REQUESTS, STATES, }; -use assert_matches::assert_matches; -use enclose::enclose; -use futures::future; -use std::any::Any; -use std::sync::{Arc, RwLock}; -use stremio_derive::Model; -use url::Url; #[test] fn default_catalog() { @@ -158,7 +161,7 @@ fn search_catalog() { let runtime = Arc::new(RwLock::new(runtime)); let selected = Selected { request: ResourceRequest { - base: Url::parse("https://v3-cinemeta.strem.io/manifest.json").unwrap(), + base: TransportUrl::parse("https://v3-cinemeta.strem.io/manifest.json").unwrap(), path: ResourcePath { resource: "catalog".to_owned(), id: "top".to_owned(), diff --git a/src/unit_tests/ctx/install_addon.rs b/src/unit_tests/ctx/install_addon.rs index 0734d237b..33b5b7b7e 100644 --- a/src/unit_tests/ctx/install_addon.rs +++ b/src/unit_tests/ctx/install_addon.rs @@ -1,8 +1,14 @@ +use std::any::Any; + +use futures::future; +use semver::Version; +use stremio_derive::Model; + use crate::constants::PROFILE_STORAGE_KEY; use crate::models::ctx::Ctx; use crate::runtime::msg::{Action, ActionCtx}; use crate::runtime::{Env, EnvFutureExt, Runtime, RuntimeAction, TryEnvFuture}; -use crate::types::addon::{Descriptor, Manifest}; +use crate::types::addon::{Descriptor, Manifest, TransportUrl}; use crate::types::api::{APIResult, SuccessResponse}; use crate::types::library::LibraryBucket; use crate::types::notifications::NotificationsBucket; @@ -12,11 +18,6 @@ use crate::types::True; use crate::unit_tests::{ default_fetch_handler, Request, TestEnv, FETCH_HANDLER, REQUESTS, STORAGE, }; -use futures::future; -use semver::Version; -use std::any::Any; -use stremio_derive::Model; -use url::Url; #[test] fn actionctx_installaddon_install() { @@ -41,7 +42,7 @@ fn actionctx_installaddon_install() { addon_catalogs: vec![], behavior_hints: Default::default(), }, - transport_url: Url::parse("https://transport_url").unwrap(), + transport_url: TransportUrl::parse("https://transport_url.com/manifest.json").unwrap(), flags: Default::default(), }; let _env_mutex = TestEnv::reset().expect("Should have exclusive lock to TestEnv"); @@ -100,7 +101,7 @@ fn actionctx_installaddon_install_with_user() { url, method, body, .. } if url == "https://api.strem.io/api/addonCollectionSet" && method == "POST" - && body == "{\"type\":\"AddonCollectionSet\",\"authKey\":\"auth_key\",\"addons\":[{\"manifest\":{\"id\":\"id\",\"version\":\"0.0.1\",\"name\":\"name\",\"contactEmail\":null,\"description\":null,\"logo\":null,\"background\":null,\"types\":[],\"resources\":[],\"idPrefixes\":null,\"catalogs\":[],\"addonCatalogs\":[],\"behaviorHints\":{\"adult\":false,\"p2p\":false,\"configurable\":false,\"configurationRequired\":false}},\"transportUrl\":\"https://transport_url/\",\"flags\":{\"official\":false,\"protected\":false}}]}" => + && body == "{\"type\":\"AddonCollectionSet\",\"authKey\":\"auth_key\",\"addons\":[{\"manifest\":{\"id\":\"id\",\"version\":\"0.0.1\",\"name\":\"name\",\"contactEmail\":null,\"description\":null,\"logo\":null,\"background\":null,\"types\":[],\"resources\":[],\"idPrefixes\":null,\"catalogs\":[],\"addonCatalogs\":[],\"behaviorHints\":{\"adult\":false,\"p2p\":false,\"configurable\":false,\"configurationRequired\":false}},\"transportUrl\":\"https://transport_url/manifest.json\",\"flags\":{\"official\":false,\"protected\":false}}]}" => { future::ok(Box::new(APIResult::Ok { result: SuccessResponse { success: True {} }, @@ -125,7 +126,7 @@ fn actionctx_installaddon_install_with_user() { addon_catalogs: vec![], behavior_hints: Default::default(), }, - transport_url: Url::parse("https://transport_url").unwrap(), + transport_url: TransportUrl::parse("https://transport_url.com/manifest.json").unwrap(), flags: Default::default(), }; let _env_mutex = TestEnv::reset().expect("Should have exclusive lock to TestEnv"); @@ -226,7 +227,7 @@ fn actionctx_installaddon_update() { addon_catalogs: vec![], behavior_hints: Default::default(), }, - transport_url: Url::parse("https://transport_url1").unwrap(), + transport_url: TransportUrl::parse("https://transport_url1.com/manifest.json").unwrap(), flags: Default::default(), }; let addon2 = Descriptor { @@ -245,7 +246,7 @@ fn actionctx_installaddon_update() { addon_catalogs: vec![], behavior_hints: Default::default(), }, - transport_url: Url::parse("https://transport_url2").unwrap(), + transport_url: TransportUrl::parse("https://transport_url2.com/manifest.json").unwrap(), flags: Default::default(), }; let _env_mutex = TestEnv::reset().expect("Should have exclusive lock to TestEnv"); @@ -270,7 +271,10 @@ fn actionctx_installaddon_update() { addon_catalogs: vec![], behavior_hints: Default::default(), }, - transport_url: Url::parse("https://transport_url1").unwrap(), + transport_url: TransportUrl::parse( + "https://transport_url1.com/manifest.json", + ) + .unwrap(), flags: Default::default(), }, addon2.to_owned(), @@ -336,7 +340,7 @@ fn actionctx_installaddon_already_installed() { addon_catalogs: vec![], behavior_hints: Default::default(), }, - transport_url: Url::parse("https://transport_url").unwrap(), + transport_url: TransportUrl::parse("https://transport_url.com/manifest.json").unwrap(), flags: Default::default(), }; let profile = Profile { diff --git a/src/unit_tests/ctx/notifications/update_notifications.rs b/src/unit_tests/ctx/notifications/update_notifications.rs index 3e6e14dd8..a95a36eb0 100644 --- a/src/unit_tests/ctx/notifications/update_notifications.rs +++ b/src/unit_tests/ctx/notifications/update_notifications.rs @@ -28,7 +28,7 @@ use crate::{ types::{ addon::{ Descriptor, Manifest, ManifestCatalog, ManifestExtra, ResourcePath, ResourceRequest, - ResourceResponse, + ResourceResponse, TransportUrl, }, library::{LibraryBucket, LibraryItem, LibraryItemState}, notifications::{NotificationItem, NotificationsBucket}, @@ -88,7 +88,7 @@ fn test_pull_notifications_and_play_in_player() { addon_catalogs: vec![], behavior_hints: Default::default(), }, - transport_url: Url::parse("https://addon_1.com/manifest.json").unwrap(), + transport_url: TransportUrl::parse("https://addon_1.com/manifest.json").unwrap(), flags: Default::default(), }); @@ -301,7 +301,7 @@ fn test_pull_notifications_and_play_in_player() { behavior_hints: Default::default(), }, meta_request: Some(ResourceRequest { - base: Url::parse("https://addon_1.com/manifest.json").unwrap(), + base: TransportUrl::parse("https://addon_1.com/manifest.json").unwrap(), path: ResourcePath { id: "tt1".to_owned(), resource: "meta".to_owned(), @@ -310,7 +310,7 @@ fn test_pull_notifications_and_play_in_player() { }, }), stream_request: Some(ResourceRequest { - base: Url::parse("https://addon_1.com/manifest.json").unwrap(), + base: TransportUrl::parse("https://addon_1.com/manifest.json").unwrap(), path: ResourcePath { resource: "stream".to_owned(), r#type: "series".to_owned(), diff --git a/src/unit_tests/ctx/pull_addons_from_api.rs b/src/unit_tests/ctx/pull_addons_from_api.rs index f364dbac3..6d72c7bf9 100644 --- a/src/unit_tests/ctx/pull_addons_from_api.rs +++ b/src/unit_tests/ctx/pull_addons_from_api.rs @@ -1,8 +1,14 @@ +use std::any::Any; + +use futures::future; +use semver::Version; +use stremio_derive::Model; + use crate::constants::{OFFICIAL_ADDONS, PROFILE_STORAGE_KEY}; use crate::models::ctx::Ctx; use crate::runtime::msg::{Action, ActionCtx}; use crate::runtime::{Env, EnvFutureExt, Runtime, RuntimeAction, TryEnvFuture}; -use crate::types::addon::{Descriptor, Manifest}; +use crate::types::addon::{Descriptor, Manifest, TransportUrl}; use crate::types::api::{APIResult, CollectionResponse}; use crate::types::library::LibraryBucket; use crate::types::notifications::NotificationsBucket; @@ -11,11 +17,6 @@ use crate::types::streams::StreamsBucket; use crate::unit_tests::{ default_fetch_handler, Request, TestEnv, FETCH_HANDLER, REQUESTS, STORAGE, }; -use futures::future; -use semver::Version; -use std::any::Any; -use stremio_derive::Model; -use url::Url; #[test] fn actionctx_pulladdonsfromapi() { @@ -35,7 +36,10 @@ fn actionctx_pulladdonsfromapi() { version: Version::new(0, 0, 1), ..official_addon.manifest.to_owned() }, - transport_url: Url::parse("https://transport_url").unwrap(), + transport_url: TransportUrl::parse( + "https://transport_url.com/manifest.json", + ) + .unwrap(), flags: official_addon.flags.to_owned(), }], ..Default::default() @@ -142,7 +146,10 @@ fn actionctx_pulladdonsfromapi_with_user() { addon_catalogs: vec![], behavior_hints: Default::default(), }, - transport_url: Url::parse("https://transport_url").unwrap(), + transport_url: TransportUrl::parse( + "https://transport_url.com/manifest.json", + ) + .unwrap(), flags: Default::default(), }], ..Default::default() diff --git a/src/unit_tests/ctx/push_addons_to_api.rs b/src/unit_tests/ctx/push_addons_to_api.rs index bafb3ecfe..c1aa8526b 100644 --- a/src/unit_tests/ctx/push_addons_to_api.rs +++ b/src/unit_tests/ctx/push_addons_to_api.rs @@ -1,7 +1,13 @@ +use std::any::Any; + +use futures::future; +use semver::Version; +use stremio_derive::Model; + use crate::models::ctx::Ctx; use crate::runtime::msg::{Action, ActionCtx}; use crate::runtime::{Env, EnvFutureExt, Runtime, RuntimeAction, TryEnvFuture}; -use crate::types::addon::{Descriptor, Manifest}; +use crate::types::addon::{Descriptor, Manifest, TransportUrl}; use crate::types::api::{APIResult, SuccessResponse}; use crate::types::library::LibraryBucket; use crate::types::notifications::NotificationsBucket; @@ -9,11 +15,6 @@ use crate::types::profile::{Auth, AuthKey, GDPRConsent, Profile, User}; use crate::types::streams::StreamsBucket; use crate::types::True; use crate::unit_tests::{default_fetch_handler, Request, TestEnv, FETCH_HANDLER, REQUESTS}; -use futures::future; -use semver::Version; -use std::any::Any; -use stremio_derive::Model; -use url::Url; #[test] fn actionctx_pushaddonstoapi() { @@ -43,7 +44,10 @@ fn actionctx_pushaddonstoapi() { addon_catalogs: vec![], behavior_hints: Default::default(), }, - transport_url: Url::parse("https://transport_url").unwrap(), + transport_url: TransportUrl::parse( + "https://transport_url.com/manifest.json", + ) + .unwrap(), flags: Default::default(), }], ..Default::default() @@ -131,7 +135,10 @@ fn actionctx_pushaddonstoapi_with_user() { addon_catalogs: vec![], behavior_hints: Default::default(), }, - transport_url: Url::parse("https://transport_url").unwrap(), + transport_url: TransportUrl::parse( + "https://transport_url.com/manifest.json", + ) + .unwrap(), flags: Default::default(), }], ..Default::default() diff --git a/src/unit_tests/ctx/uninstall_addon.rs b/src/unit_tests/ctx/uninstall_addon.rs index 80a0adaee..04e2b78f9 100644 --- a/src/unit_tests/ctx/uninstall_addon.rs +++ b/src/unit_tests/ctx/uninstall_addon.rs @@ -2,7 +2,7 @@ use crate::constants::PROFILE_STORAGE_KEY; use crate::models::ctx::Ctx; use crate::runtime::msg::{Action, ActionCtx}; use crate::runtime::{Env, EnvFutureExt, Runtime, RuntimeAction, TryEnvFuture}; -use crate::types::addon::{Descriptor, DescriptorFlags, Manifest}; +use crate::types::addon::{Descriptor, DescriptorFlags, Manifest, TransportUrl}; use crate::types::api::{APIResult, SuccessResponse}; use crate::types::library::LibraryBucket; use crate::types::notifications::NotificationsBucket; @@ -41,7 +41,7 @@ fn actionctx_uninstalladdon() { addon_catalogs: vec![], behavior_hints: Default::default(), }, - transport_url: Url::parse("https://transport_url").unwrap(), + transport_url: TransportUrl::parse("https://transport_url.com/manifest.json").unwrap(), flags: Default::default(), }; let profile = Profile { @@ -132,7 +132,7 @@ fn actionctx_uninstalladdon_with_user() { addon_catalogs: vec![], behavior_hints: Default::default(), }, - transport_url: Url::parse("https://transport_url").unwrap(), + transport_url: TransportUrl::parse("https://transport_url.com/manifest.json").unwrap(), flags: Default::default(), }; let profile = Profile { @@ -240,7 +240,7 @@ fn actionctx_uninstalladdon_protected() { addon_catalogs: vec![], behavior_hints: Default::default(), }, - transport_url: Url::parse("https://transport_url").unwrap(), + transport_url: TransportUrl::parse("https://transport_url.com/manifest.json").unwrap(), flags: DescriptorFlags { official: false, protected: true, @@ -317,7 +317,7 @@ fn actionctx_uninstalladdon_not_installed() { addon_catalogs: vec![], behavior_hints: Default::default(), }, - transport_url: Url::parse("https://transport_url").unwrap(), + transport_url: TransportUrl::parse("https://transport_url.com/manifest.json").unwrap(), flags: Default::default(), }; let profile = Profile { @@ -345,7 +345,8 @@ fn actionctx_uninstalladdon_not_installed() { runtime.dispatch(RuntimeAction { field: None, action: Action::Ctx(ActionCtx::UninstallAddon(Descriptor { - transport_url: Url::parse("https://transport_url2").unwrap(), + transport_url: TransportUrl::parse("https://transport_url2.com/manifest.json") + .unwrap(), ..addon.to_owned() })), }) diff --git a/src/unit_tests/ctx/upgrade_addon.rs b/src/unit_tests/ctx/upgrade_addon.rs index 525fbc7bf..98b55a498 100644 --- a/src/unit_tests/ctx/upgrade_addon.rs +++ b/src/unit_tests/ctx/upgrade_addon.rs @@ -2,7 +2,7 @@ use crate::constants::PROFILE_STORAGE_KEY; use crate::models::ctx::Ctx; use crate::runtime::msg::{Action, ActionCtx}; use crate::runtime::{Runtime, RuntimeAction}; -use crate::types::addon::{Descriptor, Manifest}; +use crate::types::addon::{Descriptor, Manifest, TransportUrl}; use crate::types::library::LibraryBucket; use crate::types::notifications::NotificationsBucket; use crate::types::profile::Profile; @@ -35,7 +35,7 @@ fn actionctx_addon_upgrade() { addon_catalogs: vec![], behavior_hints: Default::default(), }, - transport_url: Url::parse("https://transport_url").unwrap(), + transport_url: TransportUrl::parse("https://transport_url.com/manifest.json").unwrap(), flags: Default::default(), }; let addon1_update = Descriptor { @@ -54,7 +54,7 @@ fn actionctx_addon_upgrade() { addon_catalogs: vec![], behavior_hints: Default::default(), }, - transport_url: Url::parse("https://transport_url").unwrap(), + transport_url: TransportUrl::parse("https://transport_url.com/manifest.json").unwrap(), flags: Default::default(), }; let addon2 = Descriptor { @@ -73,7 +73,7 @@ fn actionctx_addon_upgrade() { addon_catalogs: vec![], behavior_hints: Default::default(), }, - transport_url: Url::parse("https://transport_url_other").unwrap(), + transport_url: TransportUrl::parse("https://transport_url_other").unwrap(), flags: Default::default(), }; let _env_mutex = TestEnv::reset().expect("Should have exclusive lock to TestEnv"); @@ -144,7 +144,7 @@ fn actionctx_addon_upgrade_fail_due_to_different_url() { addon_catalogs: vec![], behavior_hints: Default::default(), }, - transport_url: Url::parse("https://transport_url1").unwrap(), + transport_url: TransportUrl::parse("https://transport_url1.com/manifest.json").unwrap(), flags: Default::default(), }; let addon2 = Descriptor { @@ -163,7 +163,7 @@ fn actionctx_addon_upgrade_fail_due_to_different_url() { addon_catalogs: vec![], behavior_hints: Default::default(), }, - transport_url: Url::parse("https://transport_url2").unwrap(), + transport_url: TransportUrl::parse("https://transport_url2.com/manifest.json").unwrap(), flags: Default::default(), }; let _env_mutex = TestEnv::reset().expect("Should have exclusive lock to TestEnv"); diff --git a/src/unit_tests/deep_links/addons_deep_links.rs b/src/unit_tests/deep_links/addons_deep_links.rs index 417d86e75..4609f2e24 100644 --- a/src/unit_tests/deep_links/addons_deep_links.rs +++ b/src/unit_tests/deep_links/addons_deep_links.rs @@ -1,6 +1,6 @@ use crate::deep_links::AddonsDeepLinks; use crate::models::installed_addons_with_filters::InstalledAddonsRequest; -use crate::types::addon::{ResourcePath, ResourceRequest}; +use crate::types::addon::{ResourcePath, ResourceRequest, TransportUrl}; use std::convert::TryFrom; use std::str::FromStr; use url::Url; @@ -23,10 +23,10 @@ fn addons_deep_links_installed_addons_request_type() { #[test] fn addons_deep_links_request() { - let request = ResourceRequest { - base: Url::from_str("http://v3-cinemeta.strem.io").unwrap(), - path: ResourcePath::without_extra("addons", "movie", "com.linvo.cinemeta"), - }; + let request = ResourceRequest::new( + TransportUrl::parse("http://v3-cinemeta.strem.io").unwrap(), + ResourcePath::without_extra("addons", "movie", "com.linvo.cinemeta"), + ); let adl = AddonsDeepLinks::try_from(&request).unwrap(); assert_eq!( adl.addons, diff --git a/src/unit_tests/deep_links/discover_deep_links.rs b/src/unit_tests/deep_links/discover_deep_links.rs index fac5557f1..04dcb6e47 100644 --- a/src/unit_tests/deep_links/discover_deep_links.rs +++ b/src/unit_tests/deep_links/discover_deep_links.rs @@ -1,15 +1,12 @@ use crate::deep_links::DiscoverDeepLinks; -use crate::types::addon::{ResourcePath, ResourceRequest}; -use std::convert::TryFrom; -use std::str::FromStr; -use url::Url; +use crate::types::addon::{ResourcePath, ResourceRequest, TransportUrl}; #[test] fn discover_deep_links() { - let request = ResourceRequest { - base: Url::from_str("http://domain.root").unwrap(), - path: ResourcePath::without_extra("meta", "movie", "tt1254207"), - }; + let request = ResourceRequest::new( + TransportUrl::parse("http://domain.root/manifest.json").unwrap(), + ResourcePath::without_extra("meta", "movie", "tt1254207"), + ); let ddl = DiscoverDeepLinks::try_from(&request).unwrap(); assert_eq!( ddl.discover, diff --git a/src/unit_tests/deep_links/meta_item_deep_links.rs b/src/unit_tests/deep_links/meta_item_deep_links.rs index aedbebb54..da1a388de 100644 --- a/src/unit_tests/deep_links/meta_item_deep_links.rs +++ b/src/unit_tests/deep_links/meta_item_deep_links.rs @@ -1,9 +1,6 @@ use crate::deep_links::MetaItemDeepLinks; -use crate::types::addon::{ResourcePath, ResourceRequest}; +use crate::types::addon::{ResourcePath, ResourceRequest, TransportUrl}; use crate::types::resource::{MetaItem, MetaItemBehaviorHints, MetaItemPreview, PosterShape}; -use std::convert::TryFrom; -use std::str::FromStr; -use url::Url; #[test] fn meta_item_deep_links() { @@ -27,10 +24,10 @@ fn meta_item_deep_links() { preview: preview.clone(), videos: vec![], }; - let request = ResourceRequest { - base: Url::from_str("http://domain.root").unwrap(), - path: ResourcePath::without_extra("meta", preview.r#type.as_ref(), preview.id.as_ref()), - }; + let request = ResourceRequest::new( + TransportUrl::parse("http://domain.root/manifest.json").unwrap(), + ResourcePath::without_extra("meta", preview.r#type.as_ref(), preview.id.as_ref()), + ); let preview_midl = MetaItemDeepLinks::try_from((&preview, &request)).unwrap(); let midl = MetaItemDeepLinks::try_from((&item, &request)).unwrap(); @@ -70,10 +67,10 @@ fn meta_item_deep_links_behavior_hints() { preview: preview.clone(), videos: vec![], }; - let request = ResourceRequest { - base: Url::from_str("http://domain.root").unwrap(), - path: ResourcePath::without_extra("meta", preview.r#type.as_ref(), preview.id.as_ref()), - }; + let request = ResourceRequest::new( + TransportUrl::parse("http://domain.root/manifest.json").unwrap(), + ResourcePath::without_extra("meta", preview.r#type.as_ref(), preview.id.as_ref()), + ); let preview_midl = MetaItemDeepLinks::try_from((&preview, &request)).unwrap(); let midl = MetaItemDeepLinks::try_from((&item, &request)).unwrap(); @@ -113,10 +110,10 @@ fn meta_item_deep_links_behavior_hints_yt_id() { preview: preview.clone(), videos: vec![], }; - let request = ResourceRequest { - base: Url::from_str("http://domain.root").unwrap(), - path: ResourcePath::without_extra("meta", preview.r#type.as_ref(), preview.id.as_ref()), - }; + let request = ResourceRequest::new( + TransportUrl::parse("http://domain.root/manifest.json").unwrap(), + ResourcePath::without_extra("meta", preview.r#type.as_ref(), preview.id.as_ref()), + ); let preview_midl = MetaItemDeepLinks::try_from((&preview, &request)).unwrap(); let midl = MetaItemDeepLinks::try_from((&item, &request)).unwrap(); diff --git a/src/unit_tests/deep_links/stream_deep_links.rs b/src/unit_tests/deep_links/stream_deep_links.rs index d6beebe8f..7b567f602 100644 --- a/src/unit_tests/deep_links/stream_deep_links.rs +++ b/src/unit_tests/deep_links/stream_deep_links.rs @@ -1,13 +1,12 @@ +use base64::Engine; +use percent_encoding::utf8_percent_encode; +use url::Url; + use crate::constants::{BASE64, URI_COMPONENT_ENCODE_SET}; use crate::deep_links::StreamDeepLinks; -use crate::types::addon::{ResourcePath, ResourceRequest}; +use crate::types::addon::{ResourcePath, ResourceRequest, TransportUrl}; use crate::types::profile::Settings; use crate::types::resource::{Stream, StreamSource}; -use base64::Engine; -use percent_encoding::utf8_percent_encode; -use std::convert::TryFrom; -use std::str::FromStr; -use url::Url; const MAGNET_STR_URL: &str = "magnet:?xt=urn:btih:dd8255ecdc7ca55fb0bbf81323d87062db1f6d1c"; const HTTP_STR_URL: &str = "http://domain.root/path"; @@ -19,7 +18,7 @@ const YT_ID: &str = "aqz-KE-bpKQ"; fn stream_deep_links_magnet() { let stream = Stream { source: StreamSource::Url { - url: Url::from_str(MAGNET_STR_URL).unwrap(), + url: Url::parse(MAGNET_STR_URL).unwrap(), }, name: None, description: None, @@ -39,7 +38,7 @@ fn stream_deep_links_magnet() { fn stream_deep_links_http() { let stream = Stream { source: StreamSource::Url { - url: Url::from_str(HTTP_STR_URL).unwrap(), + url: Url::parse(HTTP_STR_URL).unwrap(), }, name: None, description: None, @@ -115,7 +114,7 @@ fn stream_deep_links_torrent() { fn stream_deep_links_external() { let stream = Stream { source: StreamSource::External { - external_url: Some(Url::from_str(HTTP_STR_URL).unwrap()), + external_url: Some(Url::parse(HTTP_STR_URL).unwrap()), android_tv_url: None, tizen_url: None, webos_url: None, @@ -173,7 +172,7 @@ fn stream_deep_links_youtube() { fn stream_deep_links_player_frame() { let stream = Stream { source: StreamSource::PlayerFrame { - player_frame_url: Url::from_str(HTTP_STR_URL).unwrap(), + player_frame_url: Url::parse(HTTP_STR_URL).unwrap(), }, name: None, description: None, @@ -201,14 +200,14 @@ fn stream_deep_links_requests() { subtitles: vec![], behavior_hints: Default::default(), }; - let stream_request = ResourceRequest { - base: Url::from_str("http://domain.root").unwrap(), - path: ResourcePath::without_extra("stream", "movie", format!("yt_id:{YT_ID}").as_str()), - }; - let meta_request = ResourceRequest { - base: Url::from_str("http://domain.root").unwrap(), - path: ResourcePath::without_extra("meta", "movie", format!("yt_id:{YT_ID}").as_str()), - }; + let stream_request = ResourceRequest::new( + TransportUrl::parse("http://domain.root/manifest.json").unwrap(), + ResourcePath::without_extra("stream", "movie", format!("yt_id:{YT_ID}").as_str()), + ); + let meta_request = ResourceRequest::new( + TransportUrl::parse("http://domain.root/manifest.json").unwrap(), + ResourcePath::without_extra("meta", "movie", format!("yt_id:{YT_ID}").as_str()), + ); let streaming_server_url = Some(Url::parse(STREAMING_SERVER_URL).unwrap()); let settings = Settings::default(); diff --git a/src/unit_tests/deep_links/video_deep_links.rs b/src/unit_tests/deep_links/video_deep_links.rs index 6307e913a..67a0424e9 100644 --- a/src/unit_tests/deep_links/video_deep_links.rs +++ b/src/unit_tests/deep_links/video_deep_links.rs @@ -1,11 +1,9 @@ use crate::constants::BASE64; use crate::deep_links::{ExternalPlayerLink, VideoDeepLinks}; -use crate::types::addon::{ResourcePath, ResourceRequest}; +use crate::types::addon::{ResourcePath, ResourceRequest, TransportUrl}; use crate::types::profile::Settings; use crate::types::resource::Video; use base64::Engine; -use std::convert::TryFrom; -use std::str::FromStr; use url::Url; const STREAMING_SERVER_URL: &str = "http://127.0.0.1:11471/"; @@ -23,10 +21,10 @@ fn video_deep_links() { series_info: None, trailer_streams: vec![], }; - let request = ResourceRequest { - base: Url::from_str("http://domain.root").unwrap(), - path: ResourcePath::without_extra("meta", "movie", format!("yt_id:{YT_ID}").as_str()), - }; + let request = ResourceRequest::new( + TransportUrl::parse("http://domain.root/manifest.json").unwrap(), + ResourcePath::without_extra("meta", "movie", format!("yt_id:{YT_ID}").as_str()), + ); let streaming_server_url = Some(Url::parse(STREAMING_SERVER_URL).unwrap()); let settings = Settings::default(); let vdl = diff --git a/src/unit_tests/env.rs b/src/unit_tests/env.rs index b458d5abd..6110b1ce1 100644 --- a/src/unit_tests/env.rs +++ b/src/unit_tests/env.rs @@ -71,7 +71,57 @@ impl TestEnv { runnable(); })) } - pub fn run_with_runtime + Clone + Send + Sync + 'static, F: FnOnce()>( + + // pub async fn handle_event(event: RuntimeEvent) + // where + // M: Model + Clone + Send + Sync + 'static, + // { + // if let RuntimeEvent::NewState(_, state) = &event { + // let mut states = STATES.write().expect("states write failed"); + // states.push(Box::new(state.to_owned()) as Box); + // }; + // let mut events = EVENTS.write().expect("events write failed"); + // events.push(Box::new(event) as Box); + // } + + // pub fn with_runtime( + // rx: Receiver>, + // runtime: &Runtime, + // runnable: F, + // ) -> JoinHandle + // where + // M: Model + Clone + Send + Sync + 'static, + // F: FnOnce(&Runtime), + // { + // tokio_current_thread::block_on_all(future::lazy(|_| { + // { + // let state = runtime.model().expect("model read failed"); + // let mut states = STATES.write().expect("states write failed"); + // states.push(Box::new(state.to_owned()) as Box); + // } + // runnable(runtime); + // })); + // tokio_current_thread::block_on_all(future::lazy(|_| { + // TestEnv::exec_concurrent(rx.for_each(move |event| { + // if let RuntimeEvent::NewState(_, state) = &event { + // let mut states = STATES.write().expect("states write failed"); + // states.push(Box::new(state.to_owned()) as Box); + // }; + // let mut events = EVENTS.write().expect("events write failed"); + // events.push(Box::new(event) as Box); + // future::ready(()) + // })); + // TestEnv::exec_concurrent(enclose!((runtime) async move { + // let mut runtime = runtime.write().expect("runtime read failed"); + // runtime.close().await.unwrap(); + // })); + // })); + // } + + pub fn run_with_runtime< + M: Model + core::fmt::Debug + Clone + Send + Sync + 'static, + F: FnOnce(), + >( rx: Receiver>, runtime: Arc>>, runnable: F, @@ -89,6 +139,7 @@ impl TestEnv { TestEnv::exec_concurrent(rx.for_each(move |event| { if let RuntimeEvent::NewState(_, state) = &event { let mut states = STATES.write().expect("states write failed"); + states.push(Box::new(state.to_owned()) as Box); }; let mut events = EVENTS.write().expect("events write failed"); diff --git a/src/unit_tests/serde/descriptor.rs b/src/unit_tests/serde/descriptor.rs index 9f507e44d..6af63f62e 100644 --- a/src/unit_tests/serde/descriptor.rs +++ b/src/unit_tests/serde/descriptor.rs @@ -1,4 +1,4 @@ -use crate::types::addon::{Descriptor, DescriptorFlags, Manifest}; +use crate::types::addon::{Descriptor, DescriptorFlags, Manifest, TransportUrl}; use crate::unit_tests::serde::default_tokens_ext::DefaultTokens; use serde_test::{assert_de_tokens, assert_tokens, Token}; use url::Url; @@ -8,7 +8,7 @@ fn descriptor() { assert_tokens( &Descriptor { manifest: Manifest::default(), - transport_url: Url::parse("https://transport_url").unwrap(), + transport_url: TransportUrl::parse("https://transport_url.com/manifest.json").unwrap(), flags: DescriptorFlags::default(), }, &[ @@ -33,7 +33,7 @@ fn descriptor() { assert_de_tokens( &Descriptor { manifest: Manifest::default(), - transport_url: Url::parse("https://transport_url").unwrap(), + transport_url: TransportUrl::parse("https://transport_url.com/manifest.json").unwrap(), flags: DescriptorFlags::default(), }, &[ diff --git a/src/unit_tests/serde/descriptor_preview.rs b/src/unit_tests/serde/descriptor_preview.rs index fa23ff6cf..2a643ebd0 100644 --- a/src/unit_tests/serde/descriptor_preview.rs +++ b/src/unit_tests/serde/descriptor_preview.rs @@ -1,14 +1,14 @@ -use crate::types::addon::{DescriptorPreview, ManifestPreview}; -use crate::unit_tests::serde::default_tokens_ext::DefaultTokens; use serde_test::{assert_tokens, Token}; -use url::Url; + +use crate::types::addon::{DescriptorPreview, ManifestPreview, TransportUrl}; +use crate::unit_tests::serde::default_tokens_ext::DefaultTokens; #[test] fn descriptor_preview() { assert_tokens( &DescriptorPreview { manifest: ManifestPreview::default(), - transport_url: Url::parse("https://transport_url").unwrap(), + transport_url: TransportUrl::parse("https://transport_url.com/manifest.json").unwrap(), }, &[ vec![ diff --git a/src/unit_tests/serde/resource_request.rs b/src/unit_tests/serde/resource_request.rs index 73241c127..8f91a7137 100644 --- a/src/unit_tests/serde/resource_request.rs +++ b/src/unit_tests/serde/resource_request.rs @@ -1,13 +1,12 @@ -use crate::types::addon::{ResourcePath, ResourceRequest}; +use crate::types::addon::{ResourcePath, ResourceRequest, TransportUrl}; use crate::unit_tests::serde::default_tokens_ext::DefaultTokens; use serde_test::{assert_tokens, Token}; -use url::Url; #[test] fn resource_request() { assert_tokens( &ResourceRequest { - base: Url::parse("https://base").unwrap(), + base: TransportUrl::parse("https://transport_url.com/manifest.json").unwrap(), path: ResourcePath::default(), }, &[