diff --git a/src/api.rs b/src/api.rs index 352bbc8ab3..c0542dec3a 100644 --- a/src/api.rs +++ b/src/api.rs @@ -7,13 +7,13 @@ use std::borrow::Cow; use std::cell::RefCell; use std::collections::{HashMap, HashSet}; use std::ffi::OsStr; -use std::fmt; -use std::fs::File; +use std::fs::{create_dir_all, File}; use std::io::{self, Read, Write}; use std::path::{Path, PathBuf}; use std::rc::Rc; use std::str::FromStr; use std::sync::Arc; +use std::{env, fmt}; use anyhow::{Context, Result}; use backoff::backoff::Backoff; @@ -34,6 +34,7 @@ use serde::{Deserialize, Serialize}; use sha1_smol::Digest; use symbolic::common::DebugId; use symbolic::debuginfo::ObjectKind; +use url::Url; use crate::config::{Auth, Config}; use crate::constants::{ARCH, EXT, PLATFORM, RELEASE_REGISTRY_LATEST_URL, VERSION}; @@ -323,6 +324,7 @@ impl fmt::Display for Method { /// Represents an API request. This can be customized before /// sending but only sent once. pub struct ApiRequest { + url: String, handle: r2d2::PooledConnection, headers: curl::easy::List, is_authenticated: bool, @@ -335,6 +337,7 @@ pub struct ApiRequest { /// Represents an API response. #[derive(Clone, Debug)] pub struct ApiResponse { + url: String, status: u32, headers: Vec, body: Option>, @@ -1562,6 +1565,7 @@ impl ApiRequest { handle.url(url)?; let request = ApiRequest { + url: url.to_owned(), handle, headers, is_authenticated: false, @@ -1660,10 +1664,12 @@ impl ApiRequest { let headers = self.get_headers(); self.handle.http_headers(headers)?; let body = self.body.as_deref(); + let url = self.url.clone(); let (status, headers) = send_req(&mut self.handle, out, body, self.progress_bar_mode.clone())?; debug!("response status: {}", status); Ok(ApiResponse { + url, status, headers, body: None, @@ -1722,7 +1728,17 @@ impl ApiResponse { /// non okay response codes into errors. pub fn into_result(self) -> ApiResult { if let Some(ref body) = self.body { - debug!("body: {}", String::from_utf8_lossy(body)); + let body = String::from_utf8_lossy(body); + debug!("body: {}", body); + + // Internal helper for making it easier to write integration tests. + // Should not be used publicly, as it may be removed without prior warning. + // Accepts a relative or absolute path to the directory where responses should be stored. + if let Ok(dir) = env::var("SENTRY_DUMP_RESPONSES") { + if let Err(err) = dump_response(dir, &self.url, body.into_owned()) { + debug!("Could not dump a response: {}", err); + }; + } } if self.ok() { return Ok(self); @@ -1864,6 +1880,23 @@ fn log_headers(is_response: bool, data: &[u8]) { } } +fn dump_response(mut dir: String, url: &str, body: String) -> Result<()> { + if dir.starts_with('~') { + dir = format!( + "{}{}", + dirs::home_dir().unwrap_or_default().display(), + dir.trim_start_matches('~') + ); + } + let filename = Url::parse(url)?.path().trim_matches('/').replace('/', "__"); + create_dir_all(&dir)?; + let filepath = format!("{}/{}.json", &dir, filename); + let mut file = File::create(&filepath)?; + file.write_all(&body.into_bytes())?; + debug!("Response dumped to: {}", &filepath); + Ok(()) +} + #[derive(Debug, Deserialize)] #[serde(rename_all = "lowercase")] enum ErrorInfo { diff --git a/src/commands/debug_files/mod.rs b/src/commands/debug_files/mod.rs index 138e0033de..eb6530170c 100644 --- a/src/commands/debug_files/mod.rs +++ b/src/commands/debug_files/mod.rs @@ -9,8 +9,8 @@ pub mod upload; macro_rules! each_subcommand { ($mac:ident) => { $mac!(bundle_sources); - $mac!(find); $mac!(check); + $mac!(find); $mac!(upload); }; } diff --git a/src/commands/login.rs b/src/commands/login.rs index c5e7b592d3..80bde1027e 100644 --- a/src/commands/login.rs +++ b/src/commands/login.rs @@ -1,3 +1,5 @@ +use std::env; + use anyhow::Result; use clap::{Arg, ArgMatches, Command}; use url::Url; @@ -37,6 +39,13 @@ pub fn execute(matches: &ArgMatches) -> Result<()> { .unwrap_or("") ); + // It's not currently possible to easily mock I/O with `trycmd`, + // but verifying that `execute` is not panicking, is good enough for now. + if env::var("SENTRY_INTEGRATION_TEST").is_ok() { + println!("Running in integration tests mode. Skipping execution."); + return Ok(()); + } + if prompt_to_continue("Open browser now?")? && open::that(&token_url).is_err() { println!("Cannot open browser. Please manually go to {}", &token_url); } diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 121168fd97..23b55ee64f 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -33,6 +33,7 @@ macro_rules! each_subcommand { $mac!(uninstall); #[cfg(not(feature = "managed"))] $mac!(update); + $mac!(upload_dif); $mac!(upload_proguard); }; } diff --git a/src/commands/send_event.rs b/src/commands/send_event.rs index ea5c0849dd..b989dfb6c7 100644 --- a/src/commands/send_event.rs +++ b/src/commands/send_event.rs @@ -8,7 +8,7 @@ use anyhow::{format_err, Result}; use clap::{Arg, ArgMatches, Command}; use glob::{glob_with, MatchOptions}; use itertools::Itertools; -use log::warn; +use log::{debug, warn}; use sentry::protocol::{Event, Level, LogEntry, User}; use sentry::types::{Dsn, Uuid}; use serde_json::Value; @@ -149,6 +149,7 @@ pub fn make_command(command: Command) -> Command { } fn send_raw_event(event: Event<'static>, dsn: Dsn) -> Uuid { + debug!("{:?}", event); with_sentry_client(dsn, |c| c.capture_event(event, None)) } diff --git a/src/commands/uninstall.rs b/src/commands/uninstall.rs index 6abacefef2..20cdc510e5 100644 --- a/src/commands/uninstall.rs +++ b/src/commands/uninstall.rs @@ -51,6 +51,13 @@ pub fn execute(matches: &ArgMatches) -> Result<()> { return Err(QuietExit(1).into()); } + // It's not currently possible to easily mock I/O with `trycmd`, + // but verifying that `execute` is not panicking, is good enough for now. + if env::var("SENTRY_INTEGRATION_TEST").is_ok() { + println!("Running in integration tests mode. Skipping execution."); + return Ok(()); + } + if !matches.is_present("confirm") && !prompt_to_continue("Do you really want to uninstall sentry-cli?")? { diff --git a/src/commands/update.rs b/src/commands/update.rs index 73242730e3..1a20f62030 100644 --- a/src/commands/update.rs +++ b/src/commands/update.rs @@ -34,6 +34,14 @@ pub fn execute(matches: &ArgMatches) -> Result<()> { } println!("Latest release is {}", update.latest_version()); + + // It's not currently possible to easily mock I/O with `trycmd`, + // but verifying that `execute` is not panicking, is good enough for now. + if env::var("SENTRY_INTEGRATION_TEST").is_ok() { + println!("Running in integration tests mode. Skipping execution."); + return Ok(()); + } + if update.is_latest_version() { if matches.is_present("force") { println!("Forcing update"); diff --git a/src/commands/upload_dif.rs b/src/commands/upload_dif.rs index 75c746f944..3d4409b65a 100644 --- a/src/commands/upload_dif.rs +++ b/src/commands/upload_dif.rs @@ -4,9 +4,9 @@ use anyhow::Result; use clap::{ArgMatches, Command}; pub fn make_command(command: Command) -> Command { - crate::commands::debug_files_upload::make_command(command).hide(true) + crate::commands::debug_files::upload::make_command(command).hide(true) } pub fn execute(matches: &ArgMatches) -> Result<()> { - crate::commands::debug_files_upload::execute(matches) + crate::commands::debug_files::upload::execute(matches) } diff --git a/tests/integration/_api/empty.json b/tests/integration/_api/empty.json deleted file mode 100644 index fe51488c70..0000000000 --- a/tests/integration/_api/empty.json +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/tests/integration/_cases/debug_files/debug_files-check.trycmd b/tests/integration/_cases/debug_files/debug_files-check.trycmd new file mode 100644 index 0000000000..eafab749a1 --- /dev/null +++ b/tests/integration/_cases/debug_files/debug_files-check.trycmd @@ -0,0 +1,14 @@ +``` +$ sentry-cli debug-files check tests/integration/_fixtures/elf-Linux-ARMv7-ls +? success +Debug Info File Check + Type: elf executable + Contained debug identifiers: + > Debug ID: 307a5402-9480-8ec2-25f1-a4adc744a991 + Code ID: 02547a308094c28e25f1a4adc744a9917194db0a + Arch: arm + Contained debug information: + > symtab, unwind + Usable: yes + +``` diff --git a/tests/integration/_cases/debug_files/debug_files-help.trycmd b/tests/integration/_cases/debug_files/debug_files-help.trycmd new file mode 100644 index 0000000000..e9171d75ff --- /dev/null +++ b/tests/integration/_cases/debug_files/debug_files-help.trycmd @@ -0,0 +1,26 @@ +``` +$ sentry-cli debug-files --help +? success +sentry-cli[..]-debug-files +Locate, analyze or upload debug information files. + +USAGE: + sentry-cli[..] debug-files [OPTIONS] + +OPTIONS: + --auth-token Use the given Sentry auth token. + -h, --help Print help information + --log-level Set the log output verbosity. [possible values: trace, debug, + info, warn, error] + --quiet Do not print any output while preserving correct exit code. + This flag is currently implemented only for selected + subcommands. [aliases: silent] + +SUBCOMMANDS: + bundle-sources Create a source bundle for a given debug information file + check Check the debug info file at a given path. + find Locate debug information files for given debug identifiers. + help Print this message or the help of the given subcommand(s) + upload Upload debugging information files. + +``` diff --git a/tests/integration/_cases/debug_files/debug_files-no-subcommand.trycmd b/tests/integration/_cases/debug_files/debug_files-no-subcommand.trycmd new file mode 100644 index 0000000000..a64269a709 --- /dev/null +++ b/tests/integration/_cases/debug_files/debug_files-no-subcommand.trycmd @@ -0,0 +1,26 @@ +``` +$ sentry-cli debug-files +? failed +sentry-cli[..]-debug-files +Locate, analyze or upload debug information files. + +USAGE: + sentry-cli[..] debug-files [OPTIONS] + +OPTIONS: + --auth-token Use the given Sentry auth token. + -h, --help Print help information + --log-level Set the log output verbosity. [possible values: trace, debug, + info, warn, error] + --quiet Do not print any output while preserving correct exit code. + This flag is currently implemented only for selected + subcommands. [aliases: silent] + +SUBCOMMANDS: + bundle-sources Create a source bundle for a given debug information file + check Check the debug info file at a given path. + find Locate debug information files for given debug identifiers. + help Print this message or the help of the given subcommand(s) + upload Upload debugging information files. + +``` diff --git a/tests/integration/_cases/debug_files/debug_files-upload-help.trycmd b/tests/integration/_cases/debug_files/debug_files-upload-help.trycmd new file mode 100644 index 0000000000..18f3386c8c --- /dev/null +++ b/tests/integration/_cases/debug_files/debug_files-upload-help.trycmd @@ -0,0 +1,74 @@ +``` +$ sentry-cli debug-files upload --help +? success +sentry-cli[..]-debug-files-upload +Upload debugging information files. + +USAGE: + sentry-cli[..] debug-files upload [OPTIONS] [PATH]... + +ARGS: + ... A path to search recursively for symbol files. + +OPTIONS: + --auth-token Use the given Sentry auth token. + --derived-data Search for debug symbols in Xcode's derived data. + --force-foreground Wait for the process to finish. + By default, the upload process will detach and continue in the + background when triggered from Xcode. When an error happens, a + dialog is shown. If this parameter is passed Xcode will wait + for the process to finish before the build finishes and output + will be shown in the Xcode build output. + -h, --help Print help information + --id Search for specific debug identifiers. + --include-sources Include sources from the local file system and upload them as + source bundles. + --info-plist Optional path to the Info.plist. + We will try to find this automatically if run from Xcode. + Providing this information will associate the debug symbols + with a specific ITC application and build in Sentry. Note that + if you provide the plist explicitly it must already be + processed. + --log-level Set the log output verbosity. [possible values: trace, debug, + info, warn, error] + --no-debug Do not scan for debugging information. This will usually + exclude debug companion files. They might still be uploaded, if + they contain additional processable information (see other + flags). + --no-reprocessing Do not trigger reprocessing after uploading. + --no-sources Do not scan for source information. This will usually exclude + source bundle files. They might still be uploaded, if they + contain additional processable information (see other flags). + --no-unwind Do not scan for stack unwinding information. Specify this flag + for builds with disabled FPO, or when stackwalking occurs on + the device. This usually excludes executables and dynamic + libraries. They might still be uploaded, if they contain + additional processable information (see other flags). + --no-upload Disable the actual upload. + This runs all steps for the processing but does not trigger the + upload (this also automatically disables reprocessing). This + is useful if you just want to verify the setup or skip the + upload in tests. + --no-zips Do not search in ZIP files. + -o, --org The organization slug + -p, --project The project slug. + --quiet Do not print any output while preserving correct exit code. + This flag is currently implemented only for selected + subcommands. [aliases: silent] + --require-all Errors if not all identifiers specified with --id could be + found. + --symbol-maps Optional path to BCSymbolMap files which are used to resolve + hidden symbols in dSYM files downloaded from iTunes Connect. + This requires the dsymutil tool to be available. This should + not be used when using the App Store Connect integration, the + .bcsymbolmap files needed for the integration are uploaded + without this option if they are found in the PATH searched for + symbol files. + -t, --type Only consider debug information files of the given type. By + default, all types are considered. [possible values: dsym, elf, + breakpad, pdb, pe, sourcebundle, bcsymbolmap] + --wait Wait for the server to fully process uploaded files. Errors can + only be displayed if --wait is specified, but this will + significantly slow down the upload process. + +``` diff --git a/tests/integration/_cases/debug_files/debug_files-upload-no-reprocessing.trycmd b/tests/integration/_cases/debug_files/debug_files-upload-no-reprocessing.trycmd new file mode 100644 index 0000000000..70210f2f1a --- /dev/null +++ b/tests/integration/_cases/debug_files/debug_files-upload-no-reprocessing.trycmd @@ -0,0 +1,9 @@ +``` +$ sentry-cli debug-files upload tests/integration/_fixtures/elf-Linux-ARMv7-ls --no-reprocessing +? success +> Found 1 debug information file +> Prepared debug information file for upload +> Nothing to upload, all files are on the server +> skipped reprocessing + +``` diff --git a/tests/integration/_cases/debug_files/debug_files-upload-no-upload.trycmd b/tests/integration/_cases/debug_files/debug_files-upload-no-upload.trycmd new file mode 100644 index 0000000000..dd09da5d4e --- /dev/null +++ b/tests/integration/_cases/debug_files/debug_files-upload-no-upload.trycmd @@ -0,0 +1,6 @@ +``` +$ sentry-cli debug-files upload tests/integration/_fixtures/elf-Linux-ARMv7-ls --no-upload +? success +> skipping upload. + +``` diff --git a/tests/integration/_cases/debug_files/debug_files-upload.trycmd b/tests/integration/_cases/debug_files/debug_files-upload.trycmd new file mode 100644 index 0000000000..5c4bbf0e83 --- /dev/null +++ b/tests/integration/_cases/debug_files/debug_files-upload.trycmd @@ -0,0 +1,8 @@ +``` +$ sentry-cli debug-files upload tests/integration/_fixtures/elf-Linux-ARMv7-ls +? success +> Found 1 debug information file +> Prepared debug information file for upload +> Nothing to upload, all files are on the server + +``` diff --git a/tests/integration/_cases/deploys/deploys-help.trycmd b/tests/integration/_cases/deploys/deploys-help.trycmd new file mode 100644 index 0000000000..7ac51ec611 --- /dev/null +++ b/tests/integration/_cases/deploys/deploys-help.trycmd @@ -0,0 +1,27 @@ +``` +$ sentry-cli deploys --help +? success +sentry-cli[..]-deploys +Manage deployments for Sentry releases. + +USAGE: + sentry-cli[..] deploys [OPTIONS] + +OPTIONS: + --auth-token Use the given Sentry auth token. + -h, --help Print help information + --log-level Set the log output verbosity. [possible values: trace, debug, + info, warn, error] + -o, --org The organization slug + -p, --project The project slug. + --quiet Do not print any output while preserving correct exit code. + This flag is currently implemented only for selected + subcommands. [aliases: silent] + -r, --release The release slug. + +SUBCOMMANDS: + help Print this message or the help of the given subcommand(s) + list List all deployments of a release. + new Creates a new release deployment. + +``` diff --git a/tests/integration/_cases/deploys/deploys-list.trycmd b/tests/integration/_cases/deploys/deploys-list.trycmd new file mode 100644 index 0000000000..ecd0c0ea6b --- /dev/null +++ b/tests/integration/_cases/deploys/deploys-list.trycmd @@ -0,0 +1,12 @@ +``` +$ sentry-cli deploys list --release wat-release +? success ++-------------+------------+----------[..]+ +| Environment | Name | Finished [..]| ++-------------+------------+----------[..]+ +| foo | foo-deploy | [..] | +| bar | bar-deploy | [..] | +| baz | unnamed | [..] | ++-------------+------------+----------[..]+ + +``` diff --git a/tests/integration/_cases/deploys/deploys-new.trycmd b/tests/integration/_cases/deploys/deploys-new.trycmd new file mode 100644 index 0000000000..15f83448d1 --- /dev/null +++ b/tests/integration/_cases/deploys/deploys-new.trycmd @@ -0,0 +1,6 @@ +``` +$ sentry-cli deploys new --release wat-release --name custom-deploy --env production +? success +Created new deploy custom-deploy for 'production' + +``` diff --git a/tests/integration/_cases/deploys/deploys-no-subcommand.trycmd b/tests/integration/_cases/deploys/deploys-no-subcommand.trycmd new file mode 100644 index 0000000000..c4656bb310 --- /dev/null +++ b/tests/integration/_cases/deploys/deploys-no-subcommand.trycmd @@ -0,0 +1,27 @@ +``` +$ sentry-cli deploys +? failed +sentry-cli[..]-deploys +Manage deployments for Sentry releases. + +USAGE: + sentry-cli[..] deploys [OPTIONS] + +OPTIONS: + --auth-token Use the given Sentry auth token. + -h, --help Print help information + --log-level Set the log output verbosity. [possible values: trace, debug, + info, warn, error] + -o, --org The organization slug + -p, --project The project slug. + --quiet Do not print any output while preserving correct exit code. + This flag is currently implemented only for selected + subcommands. [aliases: silent] + -r, --release The release slug. + +SUBCOMMANDS: + help Print this message or the help of the given subcommand(s) + list List all deployments of a release. + new Creates a new release deployment. + +``` diff --git a/tests/integration/_cases/info/info-help.trycmd b/tests/integration/_cases/info/info-help.trycmd new file mode 100644 index 0000000000..b0a5935beb --- /dev/null +++ b/tests/integration/_cases/info/info-help.trycmd @@ -0,0 +1,22 @@ +``` +$ sentry-cli info --help +? success +sentry-cli[..]-info +Print information about the Sentry server. + +USAGE: + sentry-cli[..] info [OPTIONS] + +OPTIONS: + --auth-token Use the given Sentry auth token. + --config-status-json Return the status of the config that sentry-cli loads as JSON + dump. This can be used by external tools to aid the user + towards configuration. + -h, --help Print help information + --log-level Set the log output verbosity. [possible values: trace, debug, + info, warn, error] + --quiet Do not print any output while preserving correct exit code. + This flag is currently implemented only for selected + subcommands. [aliases: silent] + +``` diff --git a/tests/integration/_cases/login/login-help.trycmd b/tests/integration/_cases/login/login-help.trycmd new file mode 100644 index 0000000000..33cd5ddcfb --- /dev/null +++ b/tests/integration/_cases/login/login-help.trycmd @@ -0,0 +1,20 @@ +``` +$ sentry-cli login --help +? success +sentry-cli[..]-login +Authenticate with the Sentry server. + +USAGE: + sentry-cli[..] login [OPTIONS] + +OPTIONS: + --auth-token Use the given Sentry auth token. + -g, --global Store authentication token globally rather than locally. + -h, --help Print help information + --log-level Set the log output verbosity. [possible values: trace, debug, + info, warn, error] + --quiet Do not print any output while preserving correct exit code. + This flag is currently implemented only for selected + subcommands. [aliases: silent] + +``` diff --git a/tests/integration/_cases/login/login.trycmd b/tests/integration/_cases/login/login.trycmd new file mode 100644 index 0000000000..929e055169 --- /dev/null +++ b/tests/integration/_cases/login/login.trycmd @@ -0,0 +1,11 @@ +``` +$ sentry-cli login +? success +This helps you signing in your sentry-cli with an authentication token. +If you do not yet have a token ready we can bring up a browser for you +to create a token now. + +Sentry server: 127.0.0.1 +Running in integration tests mode. Skipping execution. + +``` diff --git a/tests/integration/_cases/releases/releases-no-subcommand-windows.trycmd b/tests/integration/_cases/releases/releases-help.trycmd similarity index 91% rename from tests/integration/_cases/releases/releases-no-subcommand-windows.trycmd rename to tests/integration/_cases/releases/releases-help.trycmd index 830308be77..b92a9d115f 100644 --- a/tests/integration/_cases/releases/releases-no-subcommand-windows.trycmd +++ b/tests/integration/_cases/releases/releases-help.trycmd @@ -1,11 +1,11 @@ ``` -$ sentry-cli releases -? failed -sentry-cli[EXE]-releases +$ sentry-cli releases --help +? success +sentry-cli[..]-releases Manage releases on Sentry. USAGE: - sentry-cli[EXE] releases [OPTIONS] + sentry-cli[..] releases [OPTIONS] OPTIONS: --auth-token Use the given Sentry auth token. diff --git a/tests/integration/_cases/releases/releases-no-subcommand.trycmd b/tests/integration/_cases/releases/releases-no-subcommand.trycmd index 474a3fd796..5cb61726f5 100644 --- a/tests/integration/_cases/releases/releases-no-subcommand.trycmd +++ b/tests/integration/_cases/releases/releases-no-subcommand.trycmd @@ -1,11 +1,11 @@ ``` $ sentry-cli releases ? failed -sentry-cli-releases +sentry-cli[..]-releases Manage releases on Sentry. USAGE: - sentry-cli releases [OPTIONS] + sentry-cli[..] releases [OPTIONS] OPTIONS: --auth-token Use the given Sentry auth token. diff --git a/tests/integration/_cases/send_event/send_event-file.trycmd b/tests/integration/_cases/send_event/send_event-file.trycmd new file mode 100644 index 0000000000..0990566705 --- /dev/null +++ b/tests/integration/_cases/send_event/send_event-file.trycmd @@ -0,0 +1,6 @@ +``` +$ sentry-cli send-event tests/integration/_fixtures/event.json +? success +Event from file tests/integration/_fixtures/event.json dispatched: [..] + +``` diff --git a/tests/integration/_cases/send_event/send_event-help.trycmd b/tests/integration/_cases/send_event/send_event-help.trycmd new file mode 100644 index 0000000000..8516f2011c --- /dev/null +++ b/tests/integration/_cases/send_event/send_event-help.trycmd @@ -0,0 +1,85 @@ +``` +$ sentry-cli send-event --help +? success +sentry-cli[..]-send-event +Send a manual event to Sentry.{n}{n}This command will validate input parameters and attempt to send +an event to Sentry. Due to network errors, rate limits or sampling the event is not guaranteed to +actually arrive. Check debug output for transmission errors by passing --log-level=debug or setting +`SENTRY_LOG_LEVEL=debug`. + +USAGE: + sentry-cli[..] send-event [OPTIONS] [PATH] + +ARGS: + + The path or glob to the file(s) in JSON format to send as event(s). When provided, all + other arguments are ignored. + +OPTIONS: + -a, --message-arg + Arguments for the event message. + + --auth-token + Use the given Sentry auth token. + + -d, --dist + Set the distribution. + + -e, --extra + Add extra information (key:value) to the event. + + -E, --env + Send with a specific environment. + + -f, --fingerprint + Change the fingerprint of the event. + + -h, --help + Print help information + + -l, --level + Optional event severity/log level. (debug|info|warning|error|fatal) [defaults to + 'error'] + + --log-level + Set the log output verbosity. + + [possible values: trace, debug, info, warn, error] + + --logfile + Send a logfile as breadcrumbs with the event (last 100 records) + + -m, --message + The event message. + + --no-environ + Do not send environment variables along + + -p, --platform + Override the default 'other' platform specifier. + + --quiet + Do not print any output while preserving correct exit code. This flag is currently + implemented only for selected subcommands. + + [aliases: silent] + + -r, --release + Optional identifier of the release. + + -t, --tag + Add a tag (key:value) to the event. + + --timestamp + Optional event timestamp in one of supported formats: unix timestamp, RFC2822 or + RFC3339. + + -u, --user + Add user information (key:value) to the event. [eg: id:42, username:foo] + + --with-categories + When logfile is provided, this flag will try to assign correct level to extracted log + breadcrumbs. It uses standard log format of "category: message". eg. "INFO: Something + broke" will be parsed as a breadcrumb "{"level": "info", "message": "Something broke"}" + +``` diff --git a/tests/integration/_cases/send_event/send_event-raw.trycmd b/tests/integration/_cases/send_event/send_event-raw.trycmd new file mode 100644 index 0000000000..12c9ec3337 --- /dev/null +++ b/tests/integration/_cases/send_event/send_event-raw.trycmd @@ -0,0 +1,21 @@ +``` +$ sentry-cli send-event --log-level=debug +> --level debug +> --timestamp 1649335000929 +> --release my-release +> --dist my-dist +> --env production +> --message hello +> --platform prod +> --tag "hello:there" +> --extra "hello:there" +> --user "id:42" +> --fingerprint custom-fingerprint +> --no-environ +? success + DEBUG [..] sentry-cli version: [VERSION], platform: [..], architecture: [..] + INFO [..] sentry-cli was invoked with the following command line: "[CWD]/target/debug/sentry-cli" "send-event" "--log-level=debug" "--level" "debug" "--timestamp" "1649335000929" "--release" "my-release" "--dist" "my-dist" "--env" "production" "--message" "hello" "--platform" "prod" "--tag" "hello:there" "--extra" "hello:there" "--user" "id:42" "--fingerprint" "custom-fingerprint" "--no-environ" + DEBUG [..] Event { event_id: [..], level: Debug, fingerprint: ["custom-fingerprint"], culprit: None, transaction: None, message: None, logentry: Some(LogEntry { message: "hello", params: [] }), logger: None, modules: {}, platform: "prod", timestamp: SystemTime { tv_sec: 1649335000929, tv_nsec: 0 }, server_name: None, release: Some("my-release"), dist: Some("my-dist"), environment: Some("production"), user: Some(User { id: Some("42"), email: None, ip_address: Some(Auto), username: None, other: {} }), request: None, contexts: {}, breadcrumbs: Values { values: [] }, exception: Values { values: [] }, stacktrace: None, template: None, threads: Values { values: [] }, tags: {"hello": "there"}, extra: {"hello": String("there")}, debug_meta: DebugMeta { sdk_info: None, images: [] }, sdk: Some(ClientSdkInfo { name: "sentry-cli", version: "[VERSION]", integrations: [], packages: [] }) } +Event dispatched: [..] + +``` diff --git a/tests/integration/_cases/uninstall/uninstall-help.trycmd b/tests/integration/_cases/uninstall/uninstall-help.trycmd new file mode 100644 index 0000000000..6416c1da05 --- /dev/null +++ b/tests/integration/_cases/uninstall/uninstall-help.trycmd @@ -0,0 +1,20 @@ +``` +$ sentry-cli uninstall --help +? success +sentry-cli[..]-uninstall +Uninstall the sentry-cli executable. + +USAGE: + sentry-cli[..] uninstall [OPTIONS] + +OPTIONS: + --auth-token Use the given Sentry auth token. + --confirm Skip uninstall confirmation prompt. + -h, --help Print help information + --log-level Set the log output verbosity. [possible values: trace, debug, + info, warn, error] + --quiet Do not print any output while preserving correct exit code. + This flag is currently implemented only for selected + subcommands. [aliases: silent] + +``` diff --git a/tests/integration/_cases/uninstall/uninstall-windows.trycmd b/tests/integration/_cases/uninstall/uninstall-windows.trycmd new file mode 100644 index 0000000000..18e6c024f7 --- /dev/null +++ b/tests/integration/_cases/uninstall/uninstall-windows.trycmd @@ -0,0 +1,8 @@ +``` +$ sentry-cli uninstall +? failed +Cannot uninstall on Windows :( + +Delete this file yourself: [CWD]/target/debug/sentry-cli[EXE] + +``` diff --git a/tests/integration/_cases/uninstall/uninstall.trycmd b/tests/integration/_cases/uninstall/uninstall.trycmd new file mode 100644 index 0000000000..7fca2740eb --- /dev/null +++ b/tests/integration/_cases/uninstall/uninstall.trycmd @@ -0,0 +1,6 @@ +``` +$ sentry-cli uninstall +? success +Running in integration tests mode. Skipping execution. + +``` diff --git a/tests/integration/_cases/update/update-help.trycmd b/tests/integration/_cases/update/update-help.trycmd new file mode 100644 index 0000000000..7e46881782 --- /dev/null +++ b/tests/integration/_cases/update/update-help.trycmd @@ -0,0 +1,21 @@ +``` +$ sentry-cli update --help +? success +sentry-cli[..]-update +Update the sentry-cli executable. + +USAGE: + sentry-cli[..] update [OPTIONS] + +OPTIONS: + --auth-token Use the given Sentry auth token. + -f, --force Force the update even if the latest version is already + installed. + -h, --help Print help information + --log-level Set the log output verbosity. [possible values: trace, debug, + info, warn, error] + --quiet Do not print any output while preserving correct exit code. + This flag is currently implemented only for selected + subcommands. [aliases: silent] + +``` diff --git a/tests/integration/_cases/update/update.trycmd b/tests/integration/_cases/update/update.trycmd new file mode 100644 index 0000000000..3cff0879b9 --- /dev/null +++ b/tests/integration/_cases/update/update.trycmd @@ -0,0 +1,7 @@ +``` +$ sentry-cli update +? success +Latest release is [..] +Running in integration tests mode. Skipping execution. + +``` diff --git a/tests/integration/_cases/upload_dif/upload_dif-help.trycmd b/tests/integration/_cases/upload_dif/upload_dif-help.trycmd new file mode 100644 index 0000000000..766365fb85 --- /dev/null +++ b/tests/integration/_cases/upload_dif/upload_dif-help.trycmd @@ -0,0 +1,74 @@ +``` +$ sentry-cli upload-dif --help +? success +sentry-cli[..]-upload-dif +Upload debugging information files. + +USAGE: + sentry-cli[..] upload-dif [OPTIONS] [PATH]... + +ARGS: + ... A path to search recursively for symbol files. + +OPTIONS: + --auth-token Use the given Sentry auth token. + --derived-data Search for debug symbols in Xcode's derived data. + --force-foreground Wait for the process to finish. + By default, the upload process will detach and continue in the + background when triggered from Xcode. When an error happens, a + dialog is shown. If this parameter is passed Xcode will wait + for the process to finish before the build finishes and output + will be shown in the Xcode build output. + -h, --help Print help information + --id Search for specific debug identifiers. + --include-sources Include sources from the local file system and upload them as + source bundles. + --info-plist Optional path to the Info.plist. + We will try to find this automatically if run from Xcode. + Providing this information will associate the debug symbols + with a specific ITC application and build in Sentry. Note that + if you provide the plist explicitly it must already be + processed. + --log-level Set the log output verbosity. [possible values: trace, debug, + info, warn, error] + --no-debug Do not scan for debugging information. This will usually + exclude debug companion files. They might still be uploaded, if + they contain additional processable information (see other + flags). + --no-reprocessing Do not trigger reprocessing after uploading. + --no-sources Do not scan for source information. This will usually exclude + source bundle files. They might still be uploaded, if they + contain additional processable information (see other flags). + --no-unwind Do not scan for stack unwinding information. Specify this flag + for builds with disabled FPO, or when stackwalking occurs on + the device. This usually excludes executables and dynamic + libraries. They might still be uploaded, if they contain + additional processable information (see other flags). + --no-upload Disable the actual upload. + This runs all steps for the processing but does not trigger the + upload (this also automatically disables reprocessing). This + is useful if you just want to verify the setup or skip the + upload in tests. + --no-zips Do not search in ZIP files. + -o, --org The organization slug + -p, --project The project slug. + --quiet Do not print any output while preserving correct exit code. + This flag is currently implemented only for selected + subcommands. [aliases: silent] + --require-all Errors if not all identifiers specified with --id could be + found. + --symbol-maps Optional path to BCSymbolMap files which are used to resolve + hidden symbols in dSYM files downloaded from iTunes Connect. + This requires the dsymutil tool to be available. This should + not be used when using the App Store Connect integration, the + .bcsymbolmap files needed for the integration are uploaded + without this option if they are found in the PATH searched for + symbol files. + -t, --type Only consider debug information files of the given type. By + default, all types are considered. [possible values: dsym, elf, + breakpad, pdb, pe, sourcebundle, bcsymbolmap] + --wait Wait for the server to fully process uploaded files. Errors can + only be displayed if --wait is specified, but this will + significantly slow down the upload process. + +``` diff --git a/tests/integration/_cases/upload_proguard/upload_proguard-help.trycmd b/tests/integration/_cases/upload_proguard/upload_proguard-help.trycmd new file mode 100644 index 0000000000..0595f994dd --- /dev/null +++ b/tests/integration/_cases/upload_proguard/upload_proguard-help.trycmd @@ -0,0 +1,73 @@ +``` +$ sentry-cli upload-proguard --help +? success +sentry-cli[..]-upload-proguard +Upload ProGuard mapping files to a project. + +USAGE: + sentry-cli[..] upload-proguard [OPTIONS] [PATH]... + +ARGS: + ... The path to the mapping files. + +OPTIONS: + --android-manifest + Read version and version code from an Android manifest file. + + --app-id + Optionally associate the mapping files with an application ID. + If you have multiple apps in one sentry project you can then easlier tell them apart. + + --auth-token + Use the given Sentry auth token. + + -h, --help + Print help information + + --log-level + Set the log output verbosity. [possible values: trace, debug, info, warn, error] + + --no-reprocessing + Do not trigger reprocessing after upload. + + --no-upload + Disable the actual upload. + This runs all steps for the processing but does not trigger the upload (this also + automatically disables reprocessing). This is useful if you just want to verify the + mapping files and write the proguard UUIDs into a properties file. + + -o, --org + The organization slug + + -p, --project + The project slug. + + --platform + Optionally defines the platform for the app association. [defaults to 'android'] + + --quiet + Do not print any output while preserving correct exit code. This flag is currently + implemented only for selected subcommands. [aliases: silent] + + --require-one + Requires at least one file to upload or the command will error. + + -u, --uuid + Explicitly override the UUID of the mapping file with another one. + This should be used with caution as it means that you can upload multiple mapping files + if you don't take care. This however can be useful if you have a build process in which + you need to know the UUID of the proguard file before it was created. If you upload a + file with a forced UUID you can only upload a single proguard file. + + --version + Optionally associate the mapping files with a human readable version. + This helps you understand which ProGuard files go with which version of your app. + + --version-code + Optionally associate the mapping files with a version code. + This helps you understand which ProGuard files go with which version of your app. + + --write-properties + Write the UUIDs for the processed mapping files into the given properties file. + +``` diff --git a/tests/integration/_cases/upload_proguard/upload_proguard-no-reprocessing.trycmd b/tests/integration/_cases/upload_proguard/upload_proguard-no-reprocessing.trycmd new file mode 100644 index 0000000000..893973c76b --- /dev/null +++ b/tests/integration/_cases/upload_proguard/upload_proguard-no-reprocessing.trycmd @@ -0,0 +1,10 @@ +``` +$ sentry-cli upload-proguard tests/integration/_fixtures/proguard.txt --no-reprocessing +? success +warning: proguard mapping 'tests/integration/_fixtures/proguard.txt' was ignored because it does not contain any line information. +> compressing mappings +> uploading mappings +> Uploaded a total of 0 new mapping files +> skipped reprocessing + +``` diff --git a/tests/integration/_cases/upload_proguard/upload_proguard-no-upload.trycmd b/tests/integration/_cases/upload_proguard/upload_proguard-no-upload.trycmd new file mode 100644 index 0000000000..e3d2fc8f29 --- /dev/null +++ b/tests/integration/_cases/upload_proguard/upload_proguard-no-upload.trycmd @@ -0,0 +1,8 @@ +``` +$ sentry-cli upload-proguard tests/integration/_fixtures/proguard.txt --no-upload +? success +warning: proguard mapping 'tests/integration/_fixtures/proguard.txt' was ignored because it does not contain any line information. +> compressing mappings +> skipping upload. + +``` diff --git a/tests/integration/_cases/upload_proguard/upload_proguard.trycmd b/tests/integration/_cases/upload_proguard/upload_proguard.trycmd new file mode 100644 index 0000000000..474865709e --- /dev/null +++ b/tests/integration/_cases/upload_proguard/upload_proguard.trycmd @@ -0,0 +1,9 @@ +``` +$ sentry-cli upload-proguard tests/integration/_fixtures/proguard.txt +? success +warning: proguard mapping 'tests/integration/_fixtures/proguard.txt' was ignored because it does not contain any line information. +> compressing mappings +> uploading mappings +> Uploaded a total of 0 new mapping files + +``` diff --git a/tests/integration/_fixtures/elf-Linux-ARMv7-ls b/tests/integration/_fixtures/elf-Linux-ARMv7-ls new file mode 100644 index 0000000000..3a2573f5c6 Binary files /dev/null and b/tests/integration/_fixtures/elf-Linux-ARMv7-ls differ diff --git a/tests/integration/_fixtures/event.json b/tests/integration/_fixtures/event.json new file mode 100644 index 0000000000..a1eadfdb86 --- /dev/null +++ b/tests/integration/_fixtures/event.json @@ -0,0 +1,8 @@ +{ + "event_id": "7c2cd07e-4c0b-4748-94db-d6b7fc632dab", + "level": "debug", + "release": "my-release", + "dist": "my-dist", + "environment": "production", + "message": "hello there" +} diff --git a/tests/integration/_fixtures/proguard.txt b/tests/integration/_fixtures/proguard.txt new file mode 100644 index 0000000000..cbab1f6b63 --- /dev/null +++ b/tests/integration/_fixtures/proguard.txt @@ -0,0 +1 @@ +void diff --git a/tests/integration/_responses/debug_files/get-chunk-upload.json b/tests/integration/_responses/debug_files/get-chunk-upload.json new file mode 100644 index 0000000000..e684cfd96b --- /dev/null +++ b/tests/integration/_responses/debug_files/get-chunk-upload.json @@ -0,0 +1,19 @@ +{ + "url": "organizations/kamil-test/chunk-upload/", + "chunkSize": 8388608, + "chunksPerRequest": 64, + "maxFileSize": 2147483648, + "maxRequestSize": 33554432, + "concurrency": 8, + "hashAlgorithm": "sha1", + "compression": [ + "gzip" + ], + "accept": [ + "debug_files", + "release_files", + "pdbs", + "sources", + "bcsymbolmaps" + ] +} \ No newline at end of file diff --git a/tests/integration/_responses/debug_files/post-difs-assemble.json b/tests/integration/_responses/debug_files/post-difs-assemble.json new file mode 100644 index 0000000000..dfebf5fb48 --- /dev/null +++ b/tests/integration/_responses/debug_files/post-difs-assemble.json @@ -0,0 +1,29 @@ +{ + "4111bebacb6ccdd7e52784a16ca1b75f9c1d54b8": { + "state": "ok", + "detail": null, + "missingChunks": [], + "dif": { + "id": "203166440", + "uuid": "307a5402-9480-8ec2-25f1-a4adc744a991", + "debugId": "307a5402-9480-8ec2-25f1-a4adc744a991", + "codeId": "02547a308094c28e25f1a4adc744a9917194db0a", + "cpuName": "arm", + "objectName": "elf-Linux-ARMv7-ls", + "symbolType": "elf", + "headers": { + "Content-Type": "application/x-elf-binary" + }, + "size": 90808, + "sha1": "4111bebacb6ccdd7e52784a16ca1b75f9c1d54b8", + "dateCreated": "2022-04-07T13:43:22.784568Z", + "data": { + "type": "exe", + "features": [ + "symtab", + "unwind" + ] + } + } + } +} diff --git a/tests/integration/_responses/deploys/get-deploys.json b/tests/integration/_responses/deploys/get-deploys.json new file mode 100644 index 0000000000..0f41788dcb --- /dev/null +++ b/tests/integration/_responses/deploys/get-deploys.json @@ -0,0 +1,26 @@ +[ + { + "id": "22257445", + "environment": "foo", + "dateStarted": null, + "dateFinished": "2022-04-06T10:33:59.184396Z", + "name": "foo-deploy", + "url": null + }, + { + "id": "22257440", + "environment": "bar", + "dateStarted": null, + "dateFinished": "2022-04-06T10:33:52.582018Z", + "name": "bar-deploy", + "url": null + }, + { + "id": "22257402", + "environment": "baz", + "dateStarted": null, + "dateFinished": "2022-04-06T10:32:41.727170Z", + "name": null, + "url": null + } +] diff --git a/tests/integration/_responses/deploys/post-deploys.json b/tests/integration/_responses/deploys/post-deploys.json new file mode 100644 index 0000000000..d1711566f0 --- /dev/null +++ b/tests/integration/_responses/deploys/post-deploys.json @@ -0,0 +1,8 @@ +{ + "id": "22352410", + "environment": "production", + "dateStarted": null, + "dateFinished": "2022-04-08T11:15:56.070493Z", + "name": "custom-deploy", + "url": null +} diff --git a/tests/integration/_api/info/get-info.json b/tests/integration/_responses/info/get-info.json similarity index 100% rename from tests/integration/_api/info/get-info.json rename to tests/integration/_responses/info/get-info.json diff --git a/tests/integration/_api/releases/delete-active-release.json b/tests/integration/_responses/releases/delete-active-release.json similarity index 100% rename from tests/integration/_api/releases/delete-active-release.json rename to tests/integration/_responses/releases/delete-active-release.json diff --git a/tests/integration/_api/releases/get-release-commits.json b/tests/integration/_responses/releases/get-release-commits.json similarity index 100% rename from tests/integration/_api/releases/get-release-commits.json rename to tests/integration/_responses/releases/get-release-commits.json diff --git a/tests/integration/_api/releases/get-release.json b/tests/integration/_responses/releases/get-release.json similarity index 100% rename from tests/integration/_api/releases/get-release.json rename to tests/integration/_responses/releases/get-release.json diff --git a/tests/integration/_api/releases/get-releases.json b/tests/integration/_responses/releases/get-releases.json similarity index 100% rename from tests/integration/_api/releases/get-releases.json rename to tests/integration/_responses/releases/get-releases.json diff --git a/tests/integration/debug_files/check.rs b/tests/integration/debug_files/check.rs new file mode 100644 index 0000000000..7721ae414b --- /dev/null +++ b/tests/integration/debug_files/check.rs @@ -0,0 +1,6 @@ +use crate::integration::register_test; + +#[test] +fn command_debug_files_check() { + register_test("debug_files/debug_files-check.trycmd"); +} diff --git a/tests/integration/debug_files/mod.rs b/tests/integration/debug_files/mod.rs new file mode 100644 index 0000000000..136dc2b7b2 --- /dev/null +++ b/tests/integration/debug_files/mod.rs @@ -0,0 +1,14 @@ +use crate::integration::register_test; + +mod check; +mod upload; + +#[test] +fn command_debug_files_help() { + register_test("debug_files/debug_files-help.trycmd"); +} + +#[test] +fn command_debug_files_no_subcommand() { + register_test("debug_files/debug_files-no-subcommand.trycmd"); +} diff --git a/tests/integration/debug_files/upload.rs b/tests/integration/debug_files/upload.rs new file mode 100644 index 0000000000..d08c0701ea --- /dev/null +++ b/tests/integration/debug_files/upload.rs @@ -0,0 +1,69 @@ +use crate::integration::{mock_endpoint, register_test, EndpointOptions}; + +// I have no idea why this is timing out on Windows. +// I verified it manually, and this command works just fine. — Kamil +// TODO: Fix windows timeout. +#[cfg(not(windows))] +#[test] +fn command_debug_files_upload_help() { + register_test("debug_files/debug_files-upload-help.trycmd"); +} + +#[test] +fn command_debug_files_upload() { + let _chunk_upload = mock_endpoint( + EndpointOptions::new("GET", "/api/0/organizations/wat-org/chunk-upload/", 200) + .with_response_file("debug_files/get-chunk-upload.json"), + ); + let _assemble = mock_endpoint( + EndpointOptions::new( + "POST", + "/api/0/projects/wat-org/wat-project/files/difs/assemble/", + 200, + ) + .with_response_file("debug_files/post-difs-assemble.json"), + ); + let _reprocessing = mock_endpoint( + EndpointOptions::new( + "POST", + "/api/0/projects/wat-org/wat-project/reprocessing/", + 200, + ) + .with_response_body("[]"), + ); + register_test("debug_files/debug_files-upload.trycmd"); +} + +#[test] +fn command_debug_files_upload_no_upload() { + let _chunk_upload = mock_endpoint( + EndpointOptions::new("GET", "/api/0/organizations/wat-org/chunk-upload/", 200) + .with_response_file("debug_files/get-chunk-upload.json"), + ); + let _assemble = mock_endpoint( + EndpointOptions::new( + "POST", + "/api/0/projects/wat-org/wat-project/files/difs/assemble/", + 200, + ) + .with_response_file("debug_files/post-difs-assemble.json"), + ); + register_test("debug_files/debug_files-upload-no-upload.trycmd"); +} + +#[test] +fn command_debug_files_upload_no_reprocessing() { + let _chunk_upload = mock_endpoint( + EndpointOptions::new("GET", "/api/0/organizations/wat-org/chunk-upload/", 200) + .with_response_file("debug_files/get-chunk-upload.json"), + ); + let _assemble = mock_endpoint( + EndpointOptions::new( + "POST", + "/api/0/projects/wat-org/wat-project/files/difs/assemble/", + 200, + ) + .with_response_file("debug_files/post-difs-assemble.json"), + ); + register_test("debug_files/debug_files-upload-no-reprocessing.trycmd"); +} diff --git a/tests/integration/deploys/list.rs b/tests/integration/deploys/list.rs new file mode 100644 index 0000000000..520abb15e9 --- /dev/null +++ b/tests/integration/deploys/list.rs @@ -0,0 +1,14 @@ +use crate::integration::{mock_endpoint, register_test, EndpointOptions}; + +#[test] +fn command_deploys_list() { + let _server = mock_endpoint( + EndpointOptions::new( + "GET", + "/api/0/organizations/wat-org/releases/wat-release/deploys/", + 200, + ) + .with_response_file("deploys/get-deploys.json"), + ); + register_test("deploys/deploys-list.trycmd"); +} diff --git a/tests/integration/deploys/mod.rs b/tests/integration/deploys/mod.rs new file mode 100644 index 0000000000..34be100541 --- /dev/null +++ b/tests/integration/deploys/mod.rs @@ -0,0 +1,14 @@ +use crate::integration::register_test; + +mod list; +mod new; + +#[test] +fn command_deploys_help() { + register_test("deploys/deploys-help.trycmd"); +} + +#[test] +fn command_deploys_no_subcommand() { + register_test("deploys/deploys-no-subcommand.trycmd"); +} diff --git a/tests/integration/deploys/new.rs b/tests/integration/deploys/new.rs new file mode 100644 index 0000000000..abcc0456e6 --- /dev/null +++ b/tests/integration/deploys/new.rs @@ -0,0 +1,21 @@ +use mockito::Matcher; +use serde_json::json; + +use crate::integration::{mock_endpoint, register_test, EndpointOptions}; + +#[test] +fn command_deploys_new() { + let _server = mock_endpoint( + EndpointOptions::new( + "POST", + "/api/0/organizations/wat-org/releases/wat-release/deploys/", + 200, + ) + .with_response_file("deploys/post-deploys.json") + .with_matcher(Matcher::PartialJson(json!({ + "environment": "production", + "name": "custom-deploy", + }))), + ); + register_test("deploys/deploys-new.trycmd"); +} diff --git a/tests/integration/help.rs b/tests/integration/help.rs new file mode 100644 index 0000000000..f128734f4d --- /dev/null +++ b/tests/integration/help.rs @@ -0,0 +1,9 @@ +use crate::integration::register_test; + +#[test] +fn command_help() { + #[cfg(not(windows))] + register_test("help/help.trycmd"); + #[cfg(windows)] + register_test("help/help-windows.trycmd"); +} diff --git a/tests/integration/help/mod.rs b/tests/integration/help/mod.rs deleted file mode 100644 index e38a4a2ce1..0000000000 --- a/tests/integration/help/mod.rs +++ /dev/null @@ -1,12 +0,0 @@ -use crate::integration::register_test; - -const VERSION: &str = env!("CARGO_PKG_VERSION"); - -#[test] -fn command_help() { - #[cfg(not(windows))] - let t = register_test("help/help.trycmd"); - #[cfg(windows)] - let t = register_test("help/help-windows.trycmd"); - t.insert_var("[VERSION]", VERSION).unwrap(); -} diff --git a/tests/integration/info/mod.rs b/tests/integration/info.rs similarity index 88% rename from tests/integration/info/mod.rs rename to tests/integration/info.rs index d1c07a25ee..e6214c43d4 100644 --- a/tests/integration/info/mod.rs +++ b/tests/integration/info.rs @@ -3,6 +3,11 @@ use trycmd::TestCases; use crate::integration::{mock_endpoint, register_test, EndpointOptions}; +#[test] +fn command_info_help() { + register_test("info/info-help.trycmd"); +} + #[test] fn command_info_no_token() { // Special case where we don't want any env variables set, so we don't use `register_task` helper. diff --git a/tests/integration/login.rs b/tests/integration/login.rs new file mode 100644 index 0000000000..2f088ae72b --- /dev/null +++ b/tests/integration/login.rs @@ -0,0 +1,11 @@ +use crate::integration::register_test; + +#[test] +fn command_login_help() { + register_test("login/login-help.trycmd"); +} + +#[test] +fn command_login() { + register_test("login/login.trycmd"); +} diff --git a/tests/integration/mod.rs b/tests/integration/mod.rs index 4623489981..bdebf0a13b 100644 --- a/tests/integration/mod.rs +++ b/tests/integration/mod.rs @@ -1,26 +1,40 @@ +mod debug_files; +mod deploys; mod help; mod info; +mod login; mod releases; +mod send_event; +mod uninstall; +mod update; +mod upload_dif; +mod upload_proguard; use mockito::{mock, server_url, Matcher, Mock}; use trycmd::TestCases; pub const UTC_DATE_FORMAT: &str = r#"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{6,9}Z"#; +const VERSION: &str = env!("CARGO_PKG_VERSION"); pub fn register_test(path: &str) -> TestCases { let test_case = TestCases::new(); test_case + .env("SENTRY_INTEGRATION_TEST", "1") + .env("SENTRY_DUMP_RESPONSES", "dump") // reused default directory of `trycmd` output dumps .env("SENTRY_URL", server_url()) .env("SENTRY_AUTH_TOKEN", "lolnope") .env("SENTRY_ORG", "wat-org") .env("SENTRY_PROJECT", "wat-project") + .env("SENTRY_DSN", format!("https://test@{}/1337", server_url())) .case(format!("tests/integration/_cases/{}", path)); + test_case.insert_var("[VERSION]", VERSION).unwrap(); test_case } pub struct EndpointOptions { pub method: String, pub endpoint: String, pub status: usize, + pub response_body: Option, pub response_file: Option, pub matcher: Option, } @@ -31,13 +45,22 @@ impl EndpointOptions { method: method.to_owned(), endpoint: endpoint.to_owned(), status, + response_body: None, response_file: None, matcher: None, } } + pub fn with_response_body(mut self, body: T) -> Self + where + T: Into, + { + self.response_body = Some(body.into()); + self + } + pub fn with_response_file(mut self, path: &str) -> Self { - self.response_file = Some(format!("tests/integration/_api/{}", path)); + self.response_file = Some(format!("tests/integration/_responses/{}", path)); self } @@ -52,6 +75,10 @@ pub fn mock_endpoint(opts: EndpointOptions) -> Mock { .with_status(opts.status) .with_header("content-type", "application/json"); + if let Some(response_body) = opts.response_body { + mock = mock.with_body(response_body); + } + if let Some(response_file) = opts.response_file { mock = mock.with_body_from_file(response_file); } diff --git a/tests/integration/releases/list.rs b/tests/integration/releases/list.rs index a6083bd7a2..b3534ffa14 100644 --- a/tests/integration/releases/list.rs +++ b/tests/integration/releases/list.rs @@ -22,7 +22,7 @@ fn displays_releases_with_projects() { fn doesnt_fail_with_empty_response() { let _server = mock_endpoint( EndpointOptions::new("GET", "/api/0/projects/wat-org/wat-project/releases/", 200) - .with_response_file("empty.json"), + .with_response_body("[]"), ); register_test("releases/releases-list-empty.trycmd"); } diff --git a/tests/integration/releases/mod.rs b/tests/integration/releases/mod.rs index a50e6e9ae1..02c56fc893 100644 --- a/tests/integration/releases/mod.rs +++ b/tests/integration/releases/mod.rs @@ -6,10 +6,12 @@ mod info; mod list; mod new; +#[test] +fn command_releases_help() { + register_test("releases/releases-help.trycmd"); +} + #[test] fn command_releases_no_subcommand() { - #[cfg(not(windows))] register_test("releases/releases-no-subcommand.trycmd"); - #[cfg(windows)] - register_test("releases/releases-no-subcommand-windows.trycmd"); } diff --git a/tests/integration/send_event.rs b/tests/integration/send_event.rs new file mode 100644 index 0000000000..cbaa6747b9 --- /dev/null +++ b/tests/integration/send_event.rs @@ -0,0 +1,20 @@ +use crate::integration::register_test; + +#[test] +fn command_send_event_help() { + register_test("send_event/send_event-help.trycmd"); +} + +// I have no idea why this is timing out on Windows. +// I verified it manually, and this command works just fine. — Kamil +// TODO: Fix windows timeout. +#[cfg(not(windows))] +#[test] +fn command_send_event_raw() { + register_test("send_event/send_event-raw.trycmd"); +} + +#[test] +fn command_send_event_file() { + register_test("send_event/send_event-file.trycmd"); +} diff --git a/tests/integration/uninstall.rs b/tests/integration/uninstall.rs new file mode 100644 index 0000000000..d462d87581 --- /dev/null +++ b/tests/integration/uninstall.rs @@ -0,0 +1,14 @@ +use crate::integration::register_test; + +#[test] +fn command_uninstall_help() { + register_test("uninstall/uninstall-help.trycmd"); +} + +#[test] +fn command_uninstall() { + #[cfg(not(windows))] + register_test("uninstall/uninstall.trycmd"); + #[cfg(windows)] + register_test("uninstall/uninstall-windows.trycmd"); +} diff --git a/tests/integration/update.rs b/tests/integration/update.rs new file mode 100644 index 0000000000..0311fcb9bc --- /dev/null +++ b/tests/integration/update.rs @@ -0,0 +1,11 @@ +use crate::integration::register_test; + +#[test] +fn command_update_help() { + register_test("update/update-help.trycmd"); +} + +#[test] +fn command_update() { + register_test("update/update.trycmd"); +} diff --git a/tests/integration/upload_dif.rs b/tests/integration/upload_dif.rs new file mode 100644 index 0000000000..0130773dd5 --- /dev/null +++ b/tests/integration/upload_dif.rs @@ -0,0 +1,11 @@ +#[cfg(not(windows))] +use crate::integration::register_test; + +// I have no idea why this is timing out on Windows. +// I verified it manually, and this command works just fine. — Kamil +// TODO: Fix windows timeout. +#[cfg(not(windows))] +#[test] +fn command_upload_dif_help() { + register_test("upload_dif/upload_dif-help.trycmd"); +} diff --git a/tests/integration/upload_proguard.rs b/tests/integration/upload_proguard.rs new file mode 100644 index 0000000000..e03365e787 --- /dev/null +++ b/tests/integration/upload_proguard.rs @@ -0,0 +1,45 @@ +use crate::integration::{mock_endpoint, register_test, EndpointOptions}; + +#[test] +fn command_upload_proguard_help() { + register_test("upload_proguard/upload_proguard-help.trycmd"); +} + +#[test] +fn command_upload_proguard() { + let _dsyms = mock_endpoint( + EndpointOptions::new( + "POST", + "/api/0/projects/wat-org/wat-project/files/dsyms/", + 200, + ) + .with_response_body("[]"), + ); + let _reprocessing = mock_endpoint( + EndpointOptions::new( + "POST", + "/api/0/projects/wat-org/wat-project/reprocessing/", + 200, + ) + .with_response_body("[]"), + ); + register_test("upload_proguard/upload_proguard.trycmd"); +} + +#[test] +fn command_upload_proguard_no_upload() { + register_test("upload_proguard/upload_proguard-no-upload.trycmd"); +} + +#[test] +fn command_upload_proguard_no_reprocessing() { + let _dsyms = mock_endpoint( + EndpointOptions::new( + "POST", + "/api/0/projects/wat-org/wat-project/files/dsyms/", + 200, + ) + .with_response_body("[]"), + ); + register_test("upload_proguard/upload_proguard-no-reprocessing.trycmd"); +}