mirror of https://github.com/chipsenkbeil/distant
Refactor capabilities to be version instead
parent
5dbd4fbec8
commit
93657af270
@ -0,0 +1,130 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::common::{Capabilities, SemVer};
|
||||
|
||||
/// Represents version information.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct Version {
|
||||
/// General version of server (arbitrary format)
|
||||
pub server_version: String,
|
||||
|
||||
/// Protocol version
|
||||
pub protocol_version: SemVer,
|
||||
|
||||
/// Capabilities of the server
|
||||
pub capabilities: Capabilities,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::common::Capability;
|
||||
|
||||
#[test]
|
||||
fn should_be_able_to_serialize_to_json() {
|
||||
let version = Version {
|
||||
server_version: String::from("some version"),
|
||||
protocol_version: (1, 2, 3),
|
||||
capabilities: [Capability {
|
||||
kind: String::from("some kind"),
|
||||
description: String::from("some description"),
|
||||
}]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
};
|
||||
|
||||
let value = serde_json::to_value(version).unwrap();
|
||||
assert_eq!(
|
||||
value,
|
||||
serde_json::json!({
|
||||
"server_version": "some version",
|
||||
"protocol_version": [1, 2, 3],
|
||||
"capabilities": [{
|
||||
"kind": "some kind",
|
||||
"description": "some description",
|
||||
}]
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_be_able_to_deserialize_from_json() {
|
||||
let value = serde_json::json!({
|
||||
"server_version": "some version",
|
||||
"protocol_version": [1, 2, 3],
|
||||
"capabilities": [{
|
||||
"kind": "some kind",
|
||||
"description": "some description",
|
||||
}]
|
||||
});
|
||||
|
||||
let version: Version = serde_json::from_value(value).unwrap();
|
||||
assert_eq!(
|
||||
version,
|
||||
Version {
|
||||
server_version: String::from("some version"),
|
||||
protocol_version: (1, 2, 3),
|
||||
capabilities: [Capability {
|
||||
kind: String::from("some kind"),
|
||||
description: String::from("some description"),
|
||||
}]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_be_able_to_serialize_to_msgpack() {
|
||||
let version = Version {
|
||||
server_version: String::from("some version"),
|
||||
protocol_version: (1, 2, 3),
|
||||
capabilities: [Capability {
|
||||
kind: String::from("some kind"),
|
||||
description: String::from("some description"),
|
||||
}]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
};
|
||||
|
||||
// NOTE: We don't actually check the output here because it's an implementation detail
|
||||
// and could change as we change how serialization is done. This is merely to verify
|
||||
// that we can serialize since there are times when serde fails to serialize at
|
||||
// runtime.
|
||||
let _ = rmp_serde::encode::to_vec_named(&version).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_be_able_to_deserialize_from_msgpack() {
|
||||
// NOTE: It may seem odd that we are serializing just to deserialize, but this is to
|
||||
// verify that we are not corrupting or causing issues when serializing on a
|
||||
// client/server and then trying to deserialize on the other side. This has happened
|
||||
// enough times with minor changes that we need tests to verify.
|
||||
let buf = rmp_serde::encode::to_vec_named(&Version {
|
||||
server_version: String::from("some version"),
|
||||
protocol_version: (1, 2, 3),
|
||||
capabilities: [Capability {
|
||||
kind: String::from("some kind"),
|
||||
description: String::from("some description"),
|
||||
}]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let version: Version = rmp_serde::decode::from_slice(&buf).unwrap();
|
||||
assert_eq!(
|
||||
version,
|
||||
Version {
|
||||
server_version: String::from("some version"),
|
||||
protocol_version: (1, 2, 3),
|
||||
capabilities: [Capability {
|
||||
kind: String::from("some kind"),
|
||||
description: String::from("some description"),
|
||||
}]
|
||||
.into_iter()
|
||||
.collect(),
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
use indoc::indoc;
|
||||
use rstest::*;
|
||||
|
||||
use crate::cli::fixtures::*;
|
||||
|
||||
const EXPECTED_TABLE: &str = indoc! {"
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| kind | description |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| cancel_search | Supports canceling an active search against the filesystem |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| capabilities | Supports retrieving capabilities |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| copy | Supports copying files, directories, and symlinks |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| dir_create | Supports creating directory |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| dir_read | Supports reading directory |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| exists | Supports checking if a path exists |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| file_append | Supports appending to binary file |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| file_append_text | Supports appending to text file |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| file_read | Supports reading binary file |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| file_read_text | Supports reading text file |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| file_write | Supports writing binary file |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| file_write_text | Supports writing text file |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| metadata | Supports retrieving metadata about a file, directory, or symlink |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| proc_kill | Supports killing a spawned process |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| proc_resize_pty | Supports resizing the pty of a spawned process |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| proc_spawn | Supports spawning a process |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| proc_stdin | Supports sending stdin to a spawned process |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| remove | Supports removing files, directories, and symlinks |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| rename | Supports renaming files, directories, and symlinks |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| search | Supports searching filesystem using queries |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| set_permissions | Supports setting permissions on a file, directory, or symlink |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| system_info | Supports retrieving system information |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| unwatch | Supports unwatching filesystem for changes |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
| watch | Supports watching filesystem for changes |
|
||||
+------------------+------------------------------------------------------------------+
|
||||
"};
|
||||
|
||||
#[rstest]
|
||||
#[test_log::test]
|
||||
fn should_output_capabilities(ctx: DistantManagerCtx) {
|
||||
ctx.cmd("capabilities")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(EXPECTED_TABLE)
|
||||
.stderr("");
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
use distant_core::protocol::PROTOCOL_VERSION;
|
||||
use rstest::*;
|
||||
|
||||
use crate::cli::fixtures::*;
|
||||
use crate::cli::utils::TrimmedLinesMatchPredicate;
|
||||
|
||||
#[rstest]
|
||||
#[test_log::test]
|
||||
fn should_output_capabilities(ctx: DistantManagerCtx) {
|
||||
// Because all of our crates have the same version, we can expect it to match
|
||||
let package_name = "distant-core";
|
||||
let package_version = env!("CARGO_PKG_VERSION");
|
||||
let (major, minor, patch) = PROTOCOL_VERSION;
|
||||
|
||||
// Since our client and server are built the same, all capabilities should be listed with +
|
||||
// and using 4 columns since we are not using a tty
|
||||
let expected = indoc::formatdoc! {"
|
||||
Server version: {package_name} {package_version}
|
||||
Protocol version: {major}.{minor}.{patch}
|
||||
Capabilities supported (+) or not (-):
|
||||
+cancel_search +copy +dir_create +dir_read
|
||||
+exists +file_append +file_append_text +file_read
|
||||
+file_read_text +file_write +file_write_text +metadata
|
||||
+proc_kill +proc_resize_pty +proc_spawn +proc_stdin
|
||||
+remove +rename +search +set_permissions
|
||||
+system_info +unwatch +version +watch
|
||||
"};
|
||||
|
||||
ctx.cmd("version")
|
||||
.assert()
|
||||
.success()
|
||||
.stdout(TrimmedLinesMatchPredicate::new(expected))
|
||||
.stderr("");
|
||||
}
|
@ -1,9 +1,12 @@
|
||||
use predicates::prelude::*;
|
||||
use ::predicates::prelude::*;
|
||||
|
||||
mod predicates;
|
||||
mod reader;
|
||||
|
||||
pub use self::predicates::TrimmedLinesMatchPredicate;
|
||||
pub use reader::ThreadedReader;
|
||||
|
||||
/// Produces a regex predicate using the given string
|
||||
pub fn regex_pred(s: &str) -> predicates::str::RegexPredicate {
|
||||
pub fn regex_pred(s: &str) -> ::predicates::str::RegexPredicate {
|
||||
predicate::str::is_match(s).unwrap()
|
||||
}
|
||||
|
@ -0,0 +1,50 @@
|
||||
use predicates::reflection::PredicateReflection;
|
||||
use predicates::Predicate;
|
||||
use std::fmt;
|
||||
|
||||
/// Checks if lines of text match the provided, trimming each line
|
||||
/// of both before comparing.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct TrimmedLinesMatchPredicate {
|
||||
pattern: String,
|
||||
}
|
||||
|
||||
impl TrimmedLinesMatchPredicate {
|
||||
pub fn new(pattern: impl Into<String>) -> Self {
|
||||
Self {
|
||||
pattern: pattern.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for TrimmedLinesMatchPredicate {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "trimmed_lines expects {}", self.pattern)
|
||||
}
|
||||
}
|
||||
|
||||
impl Predicate<str> for TrimmedLinesMatchPredicate {
|
||||
fn eval(&self, variable: &str) -> bool {
|
||||
let mut expected = self.pattern.lines();
|
||||
let mut actual = variable.lines();
|
||||
|
||||
// Fail if we don't have the same number of lines
|
||||
// or of the trimmed result of lines don't match
|
||||
//
|
||||
// Otherwise if we finish processing all lines,
|
||||
// we are a success
|
||||
loop {
|
||||
match (expected.next(), actual.next()) {
|
||||
(Some(expected), Some(actual)) => {
|
||||
if expected.trim() != actual.trim() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
(None, None) => return true,
|
||||
_ => return false,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PredicateReflection for TrimmedLinesMatchPredicate {}
|
Loading…
Reference in New Issue