#![allow(clippy::disallowed_methods, reason = "test code")]
use std::collections::HashMap;
use std::path::Path;
use deno_cache_dir::CacheReadFileError;
use deno_cache_dir::Checksum;
use deno_cache_dir::GlobalHttpCache;
use deno_cache_dir::GlobalToLocalCopy;
use deno_cache_dir::HttpCache;
use deno_cache_dir::LocalHttpCache;
use deno_cache_dir::LocalLspHttpCache;
use deno_maybe_sync::new_rc;
use serde_json::json;
use sys_traits::impls::RealSys;
use tempfile::TempDir;
use url::Url;
fn jsr_url() -> Url {
Url::parse("https://jsr.io/").unwrap()
}
#[test]
fn test_global_create_cache() {
let dir = TempDir::new().unwrap();
let cache_path = dir.path().join("foobar");
let sys = RealSys;
let cache = GlobalHttpCache::new(sys, cache_path.clone());
assert!(!cache.dir_path().exists());
let url = Url::parse("http://example.com/foo/bar.js").unwrap();
cache.set(&url, Default::default(), b"hello world").unwrap();
assert!(cache_path.is_dir());
assert!(cache.local_path_for_url(&url).unwrap().is_file());
}
#[test]
fn test_global_get_set() {
let dir = TempDir::new().unwrap();
let sys = RealSys;
let cache = GlobalHttpCache::new(sys, dir.path().to_path_buf());
let url = Url::parse("https://deno.land/x/welcome.ts").unwrap();
let mut headers = HashMap::new();
headers.insert(
"content-type".to_string(),
"application/javascript".to_string(),
);
headers.insert("etag".to_string(), "as5625rqdsfb".to_string());
let content = b"Hello world";
cache.set(&url, headers, content).unwrap();
let key = cache.cache_item_key(&url).unwrap();
let content = String::from_utf8(
cache.get(&key, None).unwrap().unwrap().content.into_owned(),
)
.unwrap();
let headers = cache.read_headers(&key).unwrap().unwrap();
assert_eq!(content, "Hello world");
assert_eq!(
headers.get("content-type").unwrap(),
"application/javascript"
);
assert_eq!(headers.get("etag").unwrap(), "as5625rqdsfb");
assert_eq!(headers.get("foobar"), None);
let download_time = cache.read_download_time(&key).unwrap().unwrap();
let elapsed = download_time.elapsed().unwrap();
assert!(elapsed.as_secs() < 2, "Elapsed: {:?}", elapsed);
let matching_checksum =
"64ec88ca00b268e5ba1a35678a1b5316d212f4f366b2477232534a8aeca37f3c";
{
let found_content = cache
.get(&key, Some(Checksum::new(matching_checksum)))
.unwrap()
.unwrap()
.content;
assert_eq!(found_content, content.as_bytes());
}
{
let not_matching_checksum = "1234";
let err = cache
.get(&key, Some(Checksum::new(not_matching_checksum)))
.err()
.unwrap();
let err = match err {
CacheReadFileError::ChecksumIntegrity(err) => err,
_ => unreachable!(),
};
assert_eq!(err.actual, matching_checksum);
assert_eq!(err.expected, not_matching_checksum);
assert_eq!(err.url, url);
}
}
#[test]
fn test_local_global_cache() {
let temp_dir = TempDir::new().unwrap();
let global_cache_path = temp_dir.path().join("global");
let local_cache_path = temp_dir.path().join("local");
let sys = RealSys;
let global_cache =
new_rc(GlobalHttpCache::new(sys, global_cache_path.clone()));
let local_cache = LocalHttpCache::new(
local_cache_path.clone(),
global_cache.clone(),
GlobalToLocalCopy::Allow,
jsr_url(),
);
let manifest_file_path = local_cache_path.join("manifest.json");
{
let url = Url::parse("https://deno.land/x/mod.ts").unwrap();
let content = "export const test = 5;";
global_cache
.set(
&url,
HashMap::from([(
"content-type".to_string(),
"application/typescript".to_string(),
)]),
content.as_bytes(),
)
.unwrap();
let key = local_cache.cache_item_key(&url).unwrap();
assert_eq!(
String::from_utf8(
local_cache
.get(&key, None)
.unwrap()
.unwrap()
.content
.into_owned()
)
.unwrap(),
content
);
let headers = local_cache.read_headers(&key).unwrap().unwrap();
assert_eq!(headers, HashMap::new());
assert!(!manifest_file_path.exists());
std::fs::remove_dir_all(&global_cache_path).unwrap();
assert_eq!(
String::from_utf8(
local_cache
.get(&key, None)
.unwrap()
.unwrap()
.content
.into_owned()
)
.unwrap(),
content
);
}
{
let content = "export const a = 1;";
std::fs::write(local_cache_path.join("deno.land").join("main.js"), content)
.unwrap();
let url = Url::parse("https://deno.land/main.js").unwrap();
let key = local_cache.cache_item_key(&url).unwrap();
assert_eq!(
String::from_utf8(
local_cache
.get(&key, None)
.unwrap()
.unwrap()
.content
.into_owned()
)
.unwrap(),
content
);
let headers = local_cache.read_headers(&key).unwrap().unwrap();
assert_eq!(headers, HashMap::new());
}
{
let url =
Url::parse("https://deno.land/x/different_content_type.ts").unwrap();
let content = "export const test = 5;";
global_cache
.set(
&url,
HashMap::from([(
"content-type".to_string(),
"application/javascript".to_string(),
)]),
content.as_bytes(),
)
.unwrap();
let key = local_cache.cache_item_key(&url).unwrap();
assert_eq!(
String::from_utf8(
local_cache
.get(&key, None)
.unwrap()
.unwrap()
.content
.into_owned()
)
.unwrap(),
content
);
let headers = local_cache.read_headers(&key).unwrap().unwrap();
assert_eq!(
headers,
HashMap::from([(
"content-type".to_string(),
"application/javascript".to_string(),
)])
);
assert_eq!(
read_manifest(&manifest_file_path),
json!({
"modules": {
"https://deno.land/x/different_content_type.ts": {
"headers": {
"content-type": "application/javascript"
}
}
}
})
);
std::fs::remove_file(&manifest_file_path).unwrap();
let headers = local_cache.read_headers(&key).unwrap().unwrap();
assert_eq!(
headers,
HashMap::from([(
"content-type".to_string(),
"application/javascript".to_string(),
)])
);
}
std::fs::remove_dir_all(&local_cache_path).unwrap();
let local_cache = LocalHttpCache::new(
local_cache_path.clone(),
global_cache.clone(),
GlobalToLocalCopy::Allow,
jsr_url(),
);
{
let url = Url::parse("https://deno.land/x/my_file.ts").unwrap();
let content = "export const test = 5;";
global_cache
.set(
&url,
HashMap::from([
(
"content-type".to_string(),
"application/typescript".to_string(),
),
("x-typescript-types".to_string(), "./types.d.ts".to_string()),
("x-deno-warning".to_string(), "Stop right now.".to_string()),
(
"x-other-header".to_string(),
"Thank you very much.".to_string(),
),
]),
content.as_bytes(),
)
.unwrap();
let check_output = |local_cache: &LocalHttpCache<_>| {
let key = local_cache.cache_item_key(&url).unwrap();
assert_eq!(
String::from_utf8(
local_cache
.get(&key, None)
.unwrap()
.unwrap()
.content
.into_owned()
)
.unwrap(),
content
);
let headers = local_cache.read_headers(&key).unwrap().unwrap();
assert_eq!(
headers,
HashMap::from([
("x-typescript-types".to_string(), "./types.d.ts".to_string(),),
("x-deno-warning".to_string(), "Stop right now.".to_string(),)
])
);
assert_eq!(
read_manifest(&manifest_file_path),
json!({
"modules": {
"https://deno.land/x/my_file.ts": {
"headers": {
"x-deno-warning": "Stop right now.",
"x-typescript-types": "./types.d.ts"
}
}
}
})
);
};
check_output(&local_cache);
check_output(&LocalHttpCache::new(
local_cache_path.to_path_buf(),
global_cache.clone(),
GlobalToLocalCopy::Allow,
jsr_url(),
));
}
std::fs::remove_dir_all(&local_cache_path).unwrap();
let local_cache = LocalHttpCache::new(
local_cache_path.clone(),
global_cache.clone(),
GlobalToLocalCopy::Allow,
jsr_url(),
);
{
{
let url = Url::parse("https://deno.land/INVALID/Module.ts?dev").unwrap();
let content = "export const test = 5;";
global_cache
.set(&url, HashMap::new(), content.as_bytes())
.unwrap();
let key = local_cache.cache_item_key(&url).unwrap();
assert_eq!(
String::from_utf8(
local_cache
.get(&key, None)
.unwrap()
.unwrap()
.content
.into_owned()
)
.unwrap(),
content
);
let headers = local_cache.read_headers(&key).unwrap().unwrap();
assert_eq!(headers, HashMap::new());
}
{
let url = Url::parse("https://deno.land/INVALID/module2.ts").unwrap();
let content = "export const test = 4;";
global_cache
.set(&url, HashMap::new(), content.as_bytes())
.unwrap();
let key = local_cache.cache_item_key(&url).unwrap();
assert_eq!(
String::from_utf8(
local_cache
.get(&key, None)
.unwrap()
.unwrap()
.content
.into_owned()
)
.unwrap(),
content
);
assert!(
local_cache_path
.join("deno.land/#invalid_1ee01/module2.ts")
.exists()
);
let local_cache = LocalHttpCache::new(
local_cache_path.to_path_buf(),
global_cache.clone(),
GlobalToLocalCopy::Allow,
jsr_url(),
);
assert_eq!(
String::from_utf8(
local_cache
.get(&key, None)
.unwrap()
.unwrap()
.content
.into_owned()
)
.unwrap(),
content
);
}
assert_eq!(
read_manifest(&manifest_file_path),
json!({
"modules": {
"https://deno.land/INVALID/Module.ts?dev": {
}
},
"folders": {
"https://deno.land/INVALID/": "deno.land/#invalid_1ee01",
}
})
);
}
std::fs::remove_dir_all(&local_cache_path).unwrap();
let local_cache = LocalHttpCache::new(
local_cache_path.clone(),
global_cache.clone(),
GlobalToLocalCopy::Allow,
jsr_url(),
);
{
let url = Url::parse("https://deno.land/redirect.ts").unwrap();
global_cache
.set(
&url,
HashMap::from([("location".to_string(), "./x/mod.ts".to_string())]),
"Redirecting to other url...".as_bytes(),
)
.unwrap();
let key = local_cache.cache_item_key(&url).unwrap();
let headers = local_cache.read_headers(&key).unwrap().unwrap();
assert_eq!(
headers,
HashMap::from([("location".to_string(), "./x/mod.ts".to_string())])
);
assert_eq!(
read_manifest(&manifest_file_path),
json!({
"modules": {
"https://deno.land/redirect.ts": {
"headers": {
"location": "./x/mod.ts"
}
}
}
})
);
}
std::fs::remove_dir_all(&local_cache_path).unwrap();
let local_cache = LocalHttpCache::new(
local_cache_path.clone(),
global_cache.clone(),
GlobalToLocalCopy::Allow,
jsr_url(),
);
let url = Url::parse("https://deno.land/x/mod.ts").unwrap();
let matching_checksum =
"5eadcbe625a8489347fc3b229ab66bdbcbdfecedf229dfe5d0a8a399dae6c005";
let content = "export const test = 5;";
global_cache
.set(
&url,
HashMap::from([(
"content-type".to_string(),
"application/typescript".to_string(),
)]),
content.as_bytes(),
)
.unwrap();
let key = local_cache.cache_item_key(&url).unwrap();
for _ in 0..2 {
let not_matching_checksum = "1234";
let err = local_cache
.get(&key, Some(Checksum::new(not_matching_checksum)))
.err()
.unwrap();
let err = match err {
CacheReadFileError::ChecksumIntegrity(err) => err,
_ => unreachable!(),
};
assert_eq!(err.actual, matching_checksum);
assert_eq!(err.expected, not_matching_checksum);
assert_eq!(err.url, url);
}
{
let found_content = local_cache
.get(&key, Some(Checksum::new(matching_checksum)))
.unwrap()
.unwrap()
.content;
assert_eq!(found_content, content.as_bytes());
}
{
let found_content = local_cache
.get(&key, Some(Checksum::new("not matching")))
.unwrap()
.unwrap()
.content;
assert_eq!(found_content, content.as_bytes());
}
}
fn read_manifest(path: &Path) -> serde_json::Value {
let manifest = std::fs::read_to_string(path).unwrap();
serde_json::from_str(&manifest).unwrap()
}
#[test]
fn test_lsp_local_cache() {
let temp_dir = TempDir::new().unwrap();
let global_cache_path = temp_dir.path().join("global");
let local_cache_path = temp_dir.path().join("local");
let sys = RealSys;
let global_cache =
new_rc(GlobalHttpCache::new(sys, global_cache_path.to_path_buf()));
let local_cache = LocalHttpCache::new(
local_cache_path.to_path_buf(),
global_cache.clone(),
GlobalToLocalCopy::Allow,
jsr_url(),
);
let create_readonly_cache = || {
LocalLspHttpCache::new(local_cache_path.to_path_buf(), global_cache.clone())
};
{
let url = Url::parse("https://deno.land/x/mod.ts").unwrap();
let content = "export const test = 5;";
global_cache
.set(
&url,
HashMap::from([(
"content-type".to_string(),
"application/typescript".to_string(),
)]),
content.as_bytes(),
)
.unwrap();
{
let readonly_local_cache = create_readonly_cache();
let key = readonly_local_cache.cache_item_key(&url).unwrap();
assert_eq!(readonly_local_cache.get(&key, None).unwrap(), None);
}
{
let key = local_cache.cache_item_key(&url).unwrap();
assert_eq!(
String::from_utf8(
local_cache
.get(&key, None)
.unwrap()
.unwrap()
.content
.into_owned()
)
.unwrap(),
content
);
}
{
let readonly_local_cache = create_readonly_cache();
let key = readonly_local_cache.cache_item_key(&url).unwrap();
assert_eq!(
String::from_utf8(
readonly_local_cache
.get(&key, None)
.unwrap()
.unwrap()
.content
.into_owned()
)
.unwrap(),
content
);
}
{
let readonly_local_cache = create_readonly_cache();
let file_url = readonly_local_cache.get_file_url(&url);
let expected = Url::from_directory_path(&local_cache_path)
.unwrap()
.join("deno.land/x/mod.ts")
.unwrap();
assert_eq!(file_url, Some(expected));
let mapping = readonly_local_cache.get_remote_url(
local_cache_path
.join("deno.land")
.join("x")
.join("mod.ts")
.as_path(),
);
assert_eq!(mapping.as_ref(), Some(&url));
}
}
{
let url =
Url::parse("https://deno.land/x/different_content_type.ts").unwrap();
let content = "export const test = 5;";
global_cache
.set(
&url,
HashMap::from([(
"content-type".to_string(),
"application/javascript".to_string(),
)]),
content.as_bytes(),
)
.unwrap();
{
let key = local_cache.cache_item_key(&url).unwrap();
assert_eq!(
String::from_utf8(
local_cache
.get(&key, None)
.unwrap()
.unwrap()
.content
.into_owned()
)
.unwrap(),
content
);
}
{
let readonly_local_cache = create_readonly_cache();
let key = readonly_local_cache.cache_item_key(&url).unwrap();
assert_eq!(
String::from_utf8(
readonly_local_cache
.get(&key, None)
.unwrap()
.unwrap()
.content
.into_owned()
)
.unwrap(),
content
);
let file_url = readonly_local_cache.get_file_url(&url).unwrap();
let path = file_url.to_file_path().unwrap();
assert!(path.exists());
let mapping = readonly_local_cache.get_remote_url(&path);
assert_eq!(mapping.as_ref(), Some(&url));
}
}
{
let urls = [
"http://deno.land/INVALID/Module.ts?dev",
"http://deno.land/INVALID/SubDir/Module.ts?dev",
];
for url in urls {
let url = Url::parse(url).unwrap();
let content = "export const test = 5;";
global_cache
.set(&url, HashMap::new(), content.as_bytes())
.unwrap();
{
let key = local_cache.cache_item_key(&url).unwrap();
assert_eq!(
String::from_utf8(
local_cache
.get(&key, None)
.unwrap()
.unwrap()
.content
.into_owned()
)
.unwrap(),
content
);
}
{
let readonly_local_cache = create_readonly_cache();
let key = readonly_local_cache.cache_item_key(&url).unwrap();
assert_eq!(
String::from_utf8(
readonly_local_cache
.get(&key, None)
.unwrap()
.unwrap()
.content
.into_owned()
)
.unwrap(),
content
);
let file_url = readonly_local_cache.get_file_url(&url).unwrap();
let path = file_url.to_file_path().unwrap();
assert!(path.exists());
let mapping = readonly_local_cache.get_remote_url(&path);
assert_eq!(mapping.as_ref(), Some(&url));
}
}
let urls = [
"http://deno.land/INVALID/module2.ts",
"http://deno.land/INVALID/SubDir/module3.ts",
"http://deno.land/INVALID/SubDir/sub_dir/module4.ts",
];
for url in urls {
let url = Url::parse(url).unwrap();
let content = "export const test = 4;";
global_cache
.set(&url, HashMap::new(), content.as_bytes())
.unwrap();
{
let key = local_cache.cache_item_key(&url).unwrap();
assert_eq!(
String::from_utf8(
local_cache
.get(&key, None)
.unwrap()
.unwrap()
.content
.into_owned()
)
.unwrap(),
content
);
}
{
let readonly_local_cache = create_readonly_cache();
let key = readonly_local_cache.cache_item_key(&url).unwrap();
assert_eq!(
String::from_utf8(
readonly_local_cache
.get(&key, None)
.unwrap()
.unwrap()
.content
.into_owned()
)
.unwrap(),
content
);
let file_url = readonly_local_cache.get_file_url(&url).unwrap();
let path = file_url.to_file_path().unwrap();
assert!(path.exists());
let mapping = readonly_local_cache.get_remote_url(&path);
assert_eq!(mapping.as_ref(), Some(&url));
}
let local_cache = create_readonly_cache();
let file_url = local_cache.get_file_url(&url).unwrap();
let path = file_url.to_file_path().unwrap();
assert!(path.exists());
let mapping = local_cache.get_remote_url(&path);
assert_eq!(mapping.as_ref(), Some(&url));
}
}
}