0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-09 21:57:40 -04:00

refactor(upgrade): add unit tests for lsp upgrade check (#21244)

This commit is contained in:
David Sherret 2023-11-17 16:40:12 -05:00 committed by Bartek Iwańczuk
parent 04054cd787
commit 9c39172f55
No known key found for this signature in database
GPG key ID: 0C6BCDDC3B3AD750
2 changed files with 336 additions and 128 deletions

View file

@ -3115,7 +3115,7 @@ impl tower_lsp::LanguageServer for LanguageServer {
async fn initialized(&self, _: InitializedParams) { async fn initialized(&self, _: InitializedParams) {
let mut registrations = Vec::with_capacity(2); let mut registrations = Vec::with_capacity(2);
let client = { let (client, http_client) = {
let mut ls = self.0.write().await; let mut ls = self.0.write().await;
if ls if ls
.config .config
@ -3165,7 +3165,7 @@ impl tower_lsp::LanguageServer for LanguageServer {
); );
ls.maybe_testing_server = Some(test_server); ls.maybe_testing_server = Some(test_server);
} }
ls.client.clone() (ls.client.clone(), ls.http_client.clone())
}; };
for registration in registrations { for registration in registrations {
@ -3193,22 +3193,25 @@ impl tower_lsp::LanguageServer for LanguageServer {
lsp_log!("Server ready."); lsp_log!("Server ready.");
if upgrade_check_enabled() { if upgrade_check_enabled() {
let http_client = self.0.read().await.http_client.clone(); // spawn to avoid lsp send/sync requirement, but also just
match check_for_upgrades_for_lsp(http_client).await { // to ensure this initialized method returns quickly
Ok(version_info) => { spawn(async move {
client.send_did_upgrade_check_notification( match check_for_upgrades_for_lsp(http_client).await {
lsp_custom::DidUpgradeCheckNotificationParams { Ok(version_info) => {
upgrade_available: version_info.map( client.send_did_upgrade_check_notification(
|(latest_version, is_canary)| lsp_custom::UpgradeAvailable { lsp_custom::DidUpgradeCheckNotificationParams {
latest_version, upgrade_available: version_info.map(|info| {
is_canary, lsp_custom::UpgradeAvailable {
}, latest_version: info.latest_version,
), is_canary: info.is_canary,
}, }
); }),
},
);
}
Err(err) => lsp_warn!("Failed to check for upgrades: {err}"),
} }
Err(err) => lsp_warn!("Failed to check for upgrades: {err}"), });
}
} }
} }

View file

@ -12,11 +12,10 @@ use crate::util::progress_bar::ProgressBarStyle;
use crate::util::time; use crate::util::time;
use crate::version; use crate::version;
use async_trait::async_trait;
use deno_core::anyhow::bail; use deno_core::anyhow::bail;
use deno_core::anyhow::Context; use deno_core::anyhow::Context;
use deno_core::error::AnyError; use deno_core::error::AnyError;
use deno_core::futures::future::BoxFuture;
use deno_core::futures::FutureExt;
use deno_core::unsync::spawn; use deno_core::unsync::spawn;
use deno_semver::Version; use deno_semver::Version;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
@ -43,9 +42,7 @@ const UPGRADE_CHECK_FETCH_DELAY: Duration = Duration::from_millis(500);
/// Environment necessary for doing the update checker. /// Environment necessary for doing the update checker.
/// An alternate trait implementation can be provided for testing purposes. /// An alternate trait implementation can be provided for testing purposes.
trait UpdateCheckerEnvironment: Clone + Send + Sync { trait UpdateCheckerEnvironment: Clone {
fn latest_version(&self) -> BoxFuture<'static, Result<String, AnyError>>;
fn current_version(&self) -> Cow<str>;
fn read_check_file(&self) -> String; fn read_check_file(&self) -> String;
fn write_check_file(&self, text: &str); fn write_check_file(&self, text: &str);
fn current_time(&self) -> chrono::DateTime<chrono::Utc>; fn current_time(&self) -> chrono::DateTime<chrono::Utc>;
@ -53,15 +50,13 @@ trait UpdateCheckerEnvironment: Clone + Send + Sync {
#[derive(Clone)] #[derive(Clone)]
struct RealUpdateCheckerEnvironment { struct RealUpdateCheckerEnvironment {
http_client: Arc<HttpClient>,
cache_file_path: PathBuf, cache_file_path: PathBuf,
current_time: chrono::DateTime<chrono::Utc>, current_time: chrono::DateTime<chrono::Utc>,
} }
impl RealUpdateCheckerEnvironment { impl RealUpdateCheckerEnvironment {
pub fn new(http_client: Arc<HttpClient>, cache_file_path: PathBuf) -> Self { pub fn new(cache_file_path: PathBuf) -> Self {
Self { Self {
http_client,
cache_file_path, cache_file_path,
// cache the current time // cache the current time
current_time: time::utc_now(), current_time: time::utc_now(),
@ -70,22 +65,6 @@ impl RealUpdateCheckerEnvironment {
} }
impl UpdateCheckerEnvironment for RealUpdateCheckerEnvironment { impl UpdateCheckerEnvironment for RealUpdateCheckerEnvironment {
fn latest_version(&self) -> BoxFuture<'static, Result<String, AnyError>> {
let http_client = self.http_client.clone();
async move {
if version::is_canary() {
get_latest_canary_version(&http_client, false).await
} else {
get_latest_release_version(&http_client, false).await
}
}
.boxed()
}
fn current_version(&self) -> Cow<str> {
Cow::Borrowed(version::release_version_or_canary_commit_hash())
}
fn read_check_file(&self) -> String { fn read_check_file(&self) -> String {
std::fs::read_to_string(&self.cache_file_path).unwrap_or_default() std::fs::read_to_string(&self.cache_file_path).unwrap_or_default()
} }
@ -99,15 +78,82 @@ impl UpdateCheckerEnvironment for RealUpdateCheckerEnvironment {
} }
} }
struct UpdateChecker<TEnvironment: UpdateCheckerEnvironment> { #[derive(Debug, Copy, Clone)]
enum UpgradeCheckKind {
Execution,
Lsp,
}
#[async_trait(?Send)]
trait VersionProvider: Clone {
fn is_canary(&self) -> bool;
async fn latest_version(&self) -> Result<String, AnyError>;
fn current_version(&self) -> Cow<str>;
fn release_kind(&self) -> UpgradeReleaseKind {
if self.is_canary() {
UpgradeReleaseKind::Canary
} else {
UpgradeReleaseKind::Stable
}
}
}
#[derive(Clone)]
struct RealVersionProvider {
http_client: Arc<HttpClient>,
check_kind: UpgradeCheckKind,
}
impl RealVersionProvider {
pub fn new(
http_client: Arc<HttpClient>,
check_kind: UpgradeCheckKind,
) -> Self {
Self {
http_client,
check_kind,
}
}
}
#[async_trait(?Send)]
impl VersionProvider for RealVersionProvider {
fn is_canary(&self) -> bool {
version::is_canary()
}
async fn latest_version(&self) -> Result<String, AnyError> {
get_latest_version(&self.http_client, self.release_kind(), self.check_kind)
.await
}
fn current_version(&self) -> Cow<str> {
Cow::Borrowed(version::release_version_or_canary_commit_hash())
}
}
struct UpdateChecker<
TEnvironment: UpdateCheckerEnvironment,
TVersionProvider: VersionProvider,
> {
env: TEnvironment, env: TEnvironment,
version_provider: TVersionProvider,
maybe_file: Option<CheckVersionFile>, maybe_file: Option<CheckVersionFile>,
} }
impl<TEnvironment: UpdateCheckerEnvironment> UpdateChecker<TEnvironment> { impl<
pub fn new(env: TEnvironment) -> Self { TEnvironment: UpdateCheckerEnvironment,
TVersionProvider: VersionProvider,
> UpdateChecker<TEnvironment, TVersionProvider>
{
pub fn new(env: TEnvironment, version_provider: TVersionProvider) -> Self {
let maybe_file = CheckVersionFile::parse(env.read_check_file()); let maybe_file = CheckVersionFile::parse(env.read_check_file());
Self { env, maybe_file } Self {
env,
version_provider,
maybe_file,
}
} }
pub fn should_check_for_new_version(&self) -> bool { pub fn should_check_for_new_version(&self) -> bool {
@ -131,14 +177,15 @@ impl<TEnvironment: UpdateCheckerEnvironment> UpdateChecker<TEnvironment> {
// - We already check for a new version today // - We already check for a new version today
// - The user have probably upgraded today // - The user have probably upgraded today
// So we should not prompt and wait for tomorrow for the latest version to be updated again // So we should not prompt and wait for tomorrow for the latest version to be updated again
if file.current_version != self.env.current_version() { let current_version = self.version_provider.current_version();
if file.current_version != current_version {
return None; return None;
} }
if file.latest_version == self.env.current_version() { if file.latest_version == current_version {
return None; return None;
} }
if let Ok(current) = Version::parse_standard(&self.env.current_version()) { if let Ok(current) = Version::parse_standard(&current_version) {
if let Ok(latest) = Version::parse_standard(&file.latest_version) { if let Ok(latest) = Version::parse_standard(&file.latest_version) {
if current >= latest { if current >= latest {
return None; return None;
@ -201,18 +248,21 @@ pub fn check_for_upgrades(
return; return;
} }
let env = RealUpdateCheckerEnvironment::new(http_client, cache_file_path); let env = RealUpdateCheckerEnvironment::new(cache_file_path);
let update_checker = UpdateChecker::new(env); let version_provider =
RealVersionProvider::new(http_client, UpgradeCheckKind::Execution);
let update_checker = UpdateChecker::new(env, version_provider);
if update_checker.should_check_for_new_version() { if update_checker.should_check_for_new_version() {
let env = update_checker.env.clone(); let env = update_checker.env.clone();
let version_provider = update_checker.version_provider.clone();
// do this asynchronously on a separate task // do this asynchronously on a separate task
spawn(async move { spawn(async move {
// Sleep for a small amount of time to not unnecessarily impact startup // Sleep for a small amount of time to not unnecessarily impact startup
// time. // time.
tokio::time::sleep(UPGRADE_CHECK_FETCH_DELAY).await; tokio::time::sleep(UPGRADE_CHECK_FETCH_DELAY).await;
fetch_and_store_latest_version(&env).await; fetch_and_store_latest_version(&env, &version_provider).await;
}); });
} }
@ -246,39 +296,60 @@ pub fn check_for_upgrades(
} }
} }
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LspVersionUpgradeInfo {
pub latest_version: String,
pub is_canary: bool,
}
pub async fn check_for_upgrades_for_lsp( pub async fn check_for_upgrades_for_lsp(
http_client: Arc<HttpClient>, http_client: Arc<HttpClient>,
) -> Result<Option<(String, bool)>, AnyError> { ) -> Result<Option<LspVersionUpgradeInfo>, AnyError> {
if !upgrade_check_enabled() { if !upgrade_check_enabled() {
return Ok(None); return Ok(None);
} }
let is_canary = version::is_canary();
let latest_version; let version_provider =
let mut is_upgrade; RealVersionProvider::new(http_client, UpgradeCheckKind::Lsp);
if is_canary { check_for_upgrades_for_lsp_with_provider(&version_provider).await
latest_version = get_latest_canary_version(&http_client, true).await?; }
is_upgrade = latest_version != version::GIT_COMMIT_HASH;
async fn check_for_upgrades_for_lsp_with_provider(
version_provider: &impl VersionProvider,
) -> Result<Option<LspVersionUpgradeInfo>, AnyError> {
let latest_version = version_provider.latest_version().await?;
let current_version = version_provider.current_version();
if current_version == latest_version {
Ok(None) // nothing to upgrade
} else if version_provider.is_canary() {
Ok(Some(LspVersionUpgradeInfo {
latest_version,
is_canary: true,
}))
} else { } else {
latest_version = get_latest_release_version(&http_client, true).await?; if let Ok(current) = Version::parse_standard(&current_version) {
is_upgrade = true;
if let Ok(current) = Version::parse_standard(version::deno()) {
if let Ok(latest) = Version::parse_standard(&latest_version) { if let Ok(latest) = Version::parse_standard(&latest_version) {
if current >= latest { if current >= latest {
is_upgrade = false; return Ok(None); // nothing to upgrade
} }
} }
} }
}; Ok(Some(LspVersionUpgradeInfo {
Ok(is_upgrade.then_some((latest_version, is_canary))) latest_version,
is_canary: false,
}))
}
} }
async fn fetch_and_store_latest_version< async fn fetch_and_store_latest_version<
TEnvironment: UpdateCheckerEnvironment, TEnvironment: UpdateCheckerEnvironment,
TVersionProvider: VersionProvider,
>( >(
env: &TEnvironment, env: &TEnvironment,
version_provider: &TVersionProvider,
) { ) {
// Fetch latest version or commit hash from server. // Fetch latest version or commit hash from server.
let latest_version = match env.latest_version().await { let latest_version = match version_provider.latest_version().await {
Ok(latest_version) => latest_version, Ok(latest_version) => latest_version,
Err(_) => return, Err(_) => return,
}; };
@ -290,7 +361,7 @@ async fn fetch_and_store_latest_version<
.current_time() .current_time()
.sub(chrono::Duration::hours(UPGRADE_CHECK_INTERVAL + 1)), .sub(chrono::Duration::hours(UPGRADE_CHECK_INTERVAL + 1)),
last_checked: env.current_time(), last_checked: env.current_time(),
current_version: env.current_version().to_string(), current_version: version_provider.current_version().to_string(),
latest_version, latest_version,
} }
.serialize(), .serialize(),
@ -365,14 +436,18 @@ pub async fn upgrade(
passed_version passed_version
} }
None => { None => {
let latest_version = if upgrade_flags.canary { let release_kind = if upgrade_flags.canary {
log::info!("Looking up latest canary version"); log::info!("Looking up latest canary version");
get_latest_canary_version(client, false).await? UpgradeReleaseKind::Canary
} else { } else {
log::info!("Looking up latest version"); log::info!("Looking up latest version");
get_latest_release_version(client, false).await? UpgradeReleaseKind::Stable
}; };
let latest_version =
get_latest_version(client, release_kind, UpgradeCheckKind::Execution)
.await?;
let current_is_most_recent = if upgrade_flags.canary { let current_is_most_recent = if upgrade_flags.canary {
let latest_hash = &latest_version; let latest_hash = &latest_version;
crate::version::GIT_COMMIT_HASH == latest_hash crate::version::GIT_COMMIT_HASH == latest_hash
@ -479,30 +554,46 @@ pub async fn upgrade(
Ok(()) Ok(())
} }
async fn get_latest_release_version( #[derive(Debug, Clone, Copy)]
client: &HttpClient, enum UpgradeReleaseKind {
for_lsp: bool, Stable,
) -> Result<String, AnyError> { Canary,
let mut url = "https://dl.deno.land/release-latest.txt".to_string();
if for_lsp {
url.push_str("?lsp");
}
let text = client.download_text(url).await?;
let version = text.trim().to_string();
Ok(version.replace('v', ""))
} }
async fn get_latest_canary_version( async fn get_latest_version(
client: &HttpClient, client: &HttpClient,
for_lsp: bool, release_kind: UpgradeReleaseKind,
check_kind: UpgradeCheckKind,
) -> Result<String, AnyError> { ) -> Result<String, AnyError> {
let mut url = "https://dl.deno.land/canary-latest.txt".to_string(); let url = get_url(release_kind, check_kind);
if for_lsp {
url.push_str("?lsp");
}
let text = client.download_text(url).await?; let text = client.download_text(url).await?;
let version = text.trim().to_string(); Ok(normalize_version_from_server(release_kind, &text))
Ok(version) }
fn normalize_version_from_server(
release_kind: UpgradeReleaseKind,
text: &str,
) -> String {
let text = text.trim();
match release_kind {
UpgradeReleaseKind::Stable => text.trim_start_matches('v').to_string(),
UpgradeReleaseKind::Canary => text.to_string(),
}
}
fn get_url(
release_kind: UpgradeReleaseKind,
check_kind: UpgradeCheckKind,
) -> String {
let file_name = match release_kind {
UpgradeReleaseKind::Stable => "release-latest.txt",
UpgradeReleaseKind::Canary => "canary-latest.txt",
};
let query_param = match check_kind {
UpgradeCheckKind::Execution => "",
UpgradeCheckKind::Lsp => "?lsp",
};
format!("https://dl.deno.land/{}{}", file_name, query_param)
} }
async fn download_package( async fn download_package(
@ -676,9 +767,8 @@ impl CheckVersionFile {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use std::sync::Arc; use std::cell::RefCell;
use std::rc::Rc;
use deno_core::parking_lot::Mutex;
use super::*; use super::*;
@ -733,10 +823,11 @@ mod test {
#[derive(Clone)] #[derive(Clone)]
struct TestUpdateCheckerEnvironment { struct TestUpdateCheckerEnvironment {
file_text: Arc<Mutex<String>>, file_text: Rc<RefCell<String>>,
current_version: Arc<Mutex<String>>, is_canary: Rc<RefCell<bool>>,
latest_version: Arc<Mutex<Result<String, String>>>, current_version: Rc<RefCell<String>>,
time: Arc<Mutex<chrono::DateTime<chrono::Utc>>>, latest_version: Rc<RefCell<Result<String, String>>>,
time: Rc<RefCell<chrono::DateTime<chrono::Utc>>>,
} }
impl TestUpdateCheckerEnvironment { impl TestUpdateCheckerEnvironment {
@ -744,53 +835,61 @@ mod test {
Self { Self {
file_text: Default::default(), file_text: Default::default(),
current_version: Default::default(), current_version: Default::default(),
latest_version: Arc::new(Mutex::new(Ok("".to_string()))), is_canary: Default::default(),
time: Arc::new(Mutex::new(crate::util::time::utc_now())), latest_version: Rc::new(RefCell::new(Ok("".to_string()))),
time: Rc::new(RefCell::new(crate::util::time::utc_now())),
} }
} }
pub fn add_hours(&self, hours: i64) { pub fn add_hours(&self, hours: i64) {
let mut time = self.time.lock(); let mut time = self.time.borrow_mut();
*time = time *time = time
.checked_add_signed(chrono::Duration::hours(hours)) .checked_add_signed(chrono::Duration::hours(hours))
.unwrap(); .unwrap();
} }
pub fn set_file_text(&self, text: &str) { pub fn set_file_text(&self, text: &str) {
*self.file_text.lock() = text.to_string(); *self.file_text.borrow_mut() = text.to_string();
} }
pub fn set_current_version(&self, version: &str) { pub fn set_current_version(&self, version: &str) {
*self.current_version.lock() = version.to_string(); *self.current_version.borrow_mut() = version.to_string();
} }
pub fn set_latest_version(&self, version: &str) { pub fn set_latest_version(&self, version: &str) {
*self.latest_version.lock() = Ok(version.to_string()); *self.latest_version.borrow_mut() = Ok(version.to_string());
} }
pub fn set_latest_version_err(&self, err: &str) { pub fn set_latest_version_err(&self, err: &str) {
*self.latest_version.lock() = Err(err.to_string()); *self.latest_version.borrow_mut() = Err(err.to_string());
}
pub fn set_is_canary(&self, is_canary: bool) {
*self.is_canary.borrow_mut() = is_canary;
}
}
#[async_trait(?Send)]
impl VersionProvider for TestUpdateCheckerEnvironment {
fn is_canary(&self) -> bool {
*self.is_canary.borrow()
}
async fn latest_version(&self) -> Result<String, AnyError> {
match self.latest_version.borrow().clone() {
Ok(result) => Ok(result),
Err(err) => bail!("{}", err),
}
}
fn current_version(&self) -> Cow<str> {
Cow::Owned(self.current_version.borrow().clone())
} }
} }
impl UpdateCheckerEnvironment for TestUpdateCheckerEnvironment { impl UpdateCheckerEnvironment for TestUpdateCheckerEnvironment {
fn latest_version(&self) -> BoxFuture<'static, Result<String, AnyError>> {
let env = self.clone();
async move {
match env.latest_version.lock().clone() {
Ok(result) => Ok(result),
Err(err) => bail!("{}", err),
}
}
.boxed()
}
fn current_version(&self) -> Cow<str> {
Cow::Owned(self.current_version.lock().clone())
}
fn read_check_file(&self) -> String { fn read_check_file(&self) -> String {
self.file_text.lock().clone() self.file_text.borrow().clone()
} }
fn write_check_file(&self, text: &str) { fn write_check_file(&self, text: &str) {
@ -798,7 +897,7 @@ mod test {
} }
fn current_time(&self) -> chrono::DateTime<chrono::Utc> { fn current_time(&self) -> chrono::DateTime<chrono::Utc> {
*self.time.lock() *self.time.borrow()
} }
} }
@ -807,17 +906,17 @@ mod test {
let env = TestUpdateCheckerEnvironment::new(); let env = TestUpdateCheckerEnvironment::new();
env.set_current_version("1.0.0"); env.set_current_version("1.0.0");
env.set_latest_version("1.1.0"); env.set_latest_version("1.1.0");
let checker = UpdateChecker::new(env.clone()); let checker = UpdateChecker::new(env.clone(), env.clone());
// no version, so we should check, but not prompt // no version, so we should check, but not prompt
assert!(checker.should_check_for_new_version()); assert!(checker.should_check_for_new_version());
assert_eq!(checker.should_prompt(), None); assert_eq!(checker.should_prompt(), None);
// store the latest version // store the latest version
fetch_and_store_latest_version(&env).await; fetch_and_store_latest_version(&env, &env).await;
// reload // reload
let checker = UpdateChecker::new(env.clone()); let checker = UpdateChecker::new(env.clone(), env.clone());
// should not check for latest version because we just did // should not check for latest version because we just did
assert!(!checker.should_check_for_new_version()); assert!(!checker.should_check_for_new_version());
@ -835,16 +934,16 @@ mod test {
assert!(checker.should_check_for_new_version()); assert!(checker.should_check_for_new_version());
assert_eq!(checker.should_prompt(), Some("1.1.0".to_string())); assert_eq!(checker.should_prompt(), Some("1.1.0".to_string()));
fetch_and_store_latest_version(&env).await; fetch_and_store_latest_version(&env, &env).await;
// reload and store that we prompted // reload and store that we prompted
let checker = UpdateChecker::new(env.clone()); let checker = UpdateChecker::new(env.clone(), env.clone());
assert!(!checker.should_check_for_new_version()); assert!(!checker.should_check_for_new_version());
assert_eq!(checker.should_prompt(), Some("1.2.0".to_string())); assert_eq!(checker.should_prompt(), Some("1.2.0".to_string()));
checker.store_prompted(); checker.store_prompted();
// reload and it should now say not to prompt // reload and it should now say not to prompt
let checker = UpdateChecker::new(env.clone()); let checker = UpdateChecker::new(env.clone(), env.clone());
assert!(!checker.should_check_for_new_version()); assert!(!checker.should_check_for_new_version());
assert_eq!(checker.should_prompt(), None); assert_eq!(checker.should_prompt(), None);
@ -864,7 +963,7 @@ mod test {
env.set_latest_version("1.3.0"); env.set_latest_version("1.3.0");
// this will silently fail // this will silently fail
fetch_and_store_latest_version(&env).await; fetch_and_store_latest_version(&env, &env).await;
assert!(checker.should_check_for_new_version()); assert!(checker.should_check_for_new_version());
assert_eq!(checker.should_prompt(), None); assert_eq!(checker.should_prompt(), None);
} }
@ -884,7 +983,7 @@ mod test {
env.write_check_file(&file_content); env.write_check_file(&file_content);
env.set_current_version("1.27.0"); env.set_current_version("1.27.0");
env.set_latest_version("1.26.2"); env.set_latest_version("1.26.2");
let checker = UpdateChecker::new(env); let checker = UpdateChecker::new(env.clone(), env);
// since currently running version is newer than latest available (eg. CDN // since currently running version is newer than latest available (eg. CDN
// propagation might be delated) we should not prompt // propagation might be delated) we should not prompt
@ -906,7 +1005,113 @@ mod test {
env.write_check_file(&file_content); env.write_check_file(&file_content);
// simulate an upgrade done to a canary version // simulate an upgrade done to a canary version
env.set_current_version("61fbfabe440f1cfffa7b8d17426ffdece4d430d0"); env.set_current_version("61fbfabe440f1cfffa7b8d17426ffdece4d430d0");
let checker = UpdateChecker::new(env); let checker = UpdateChecker::new(env.clone(), env);
assert_eq!(checker.should_prompt(), None); assert_eq!(checker.should_prompt(), None);
} }
#[test]
fn test_get_url() {
assert_eq!(
get_url(UpgradeReleaseKind::Canary, UpgradeCheckKind::Execution),
"https://dl.deno.land/canary-latest.txt"
);
assert_eq!(
get_url(UpgradeReleaseKind::Canary, UpgradeCheckKind::Lsp),
"https://dl.deno.land/canary-latest.txt?lsp"
);
assert_eq!(
get_url(UpgradeReleaseKind::Stable, UpgradeCheckKind::Execution),
"https://dl.deno.land/release-latest.txt"
);
assert_eq!(
get_url(UpgradeReleaseKind::Stable, UpgradeCheckKind::Lsp),
"https://dl.deno.land/release-latest.txt?lsp"
);
}
#[test]
fn test_normalize_version_server() {
// should strip v for stable
assert_eq!(
normalize_version_from_server(UpgradeReleaseKind::Stable, "v1.0.0"),
"1.0.0"
);
// should not replace v after start
assert_eq!(
normalize_version_from_server(
UpgradeReleaseKind::Stable,
" v1.0.0-test-v\n\n "
),
"1.0.0-test-v"
);
// should not strip v for canary
assert_eq!(
normalize_version_from_server(
UpgradeReleaseKind::Canary,
" v1452345asdf \n\n "
),
"v1452345asdf"
);
}
#[tokio::test]
async fn test_upgrades_lsp() {
let env = TestUpdateCheckerEnvironment::new();
env.set_current_version("1.0.0");
env.set_latest_version("2.0.0");
// greater
{
let maybe_info = check_for_upgrades_for_lsp_with_provider(&env)
.await
.unwrap();
assert_eq!(
maybe_info,
Some(LspVersionUpgradeInfo {
latest_version: "2.0.0".to_string(),
is_canary: false,
})
);
}
// equal
{
env.set_latest_version("1.0.0");
let maybe_info = check_for_upgrades_for_lsp_with_provider(&env)
.await
.unwrap();
assert_eq!(maybe_info, None);
}
// less
{
env.set_latest_version("0.9.0");
let maybe_info = check_for_upgrades_for_lsp_with_provider(&env)
.await
.unwrap();
assert_eq!(maybe_info, None);
}
// canary equal
{
env.set_current_version("123");
env.set_latest_version("123");
env.set_is_canary(true);
let maybe_info = check_for_upgrades_for_lsp_with_provider(&env)
.await
.unwrap();
assert_eq!(maybe_info, None);
}
// canary different
{
env.set_latest_version("1234");
let maybe_info = check_for_upgrades_for_lsp_with_provider(&env)
.await
.unwrap();
assert_eq!(
maybe_info,
Some(LspVersionUpgradeInfo {
latest_version: "1234".to_string(),
is_canary: true,
})
);
}
}
} }