Skip to content

Add yaml test runner project #98

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 130 commits into from
May 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
130 commits
Select commit Hold shift + click to select a range
9ae72b5
Start of yaml test runner implementation
russcam Feb 14, 2020
65c83b4
start of read_do
russcam Feb 26, 2020
ed27b0a
Reference api_generator from yaml_test_runner
russcam Mar 2, 2020
e4ff4e4
return Result types
russcam Mar 2, 2020
22ab24b
tidy up
russcam Mar 3, 2020
bd7dd71
Start of test file generation
russcam Mar 3, 2020
06784f0
Generate tests WIP
russcam Mar 3, 2020
4621521
Fix directory and module names
russcam Mar 3, 2020
a089ed8
Handle param string arrays
russcam Mar 3, 2020
2ea69b4
start building parts variant
russcam Mar 4, 2020
559682f
Refactor components into ApiCall
russcam Mar 4, 2020
ee2a4d2
Handle ignore number or array
russcam Mar 4, 2020
1f86565
Propagate unsupported values
russcam Mar 4, 2020
e3d5a40
Handle array parts
russcam Mar 4, 2020
2c33d60
Handle enum bool params
russcam Mar 4, 2020
d56c228
Add reqired client modules to generated tests
russcam Mar 4, 2020
f009b9e
Handle string params enums and lists
russcam Mar 5, 2020
70a73c8
Refactor setup/teardown generation into function
russcam Mar 5, 2020
3750263
Deduplicate generated method names
russcam Mar 5, 2020
9807b29
to_string API Url parts of bool and integer
russcam Mar 5, 2020
a65b3bd
Refactor api call components
russcam Mar 5, 2020
cf7dd11
move endpoint lookup onto Api impl
russcam Mar 5, 2020
0683c5b
impl From<> for TrackTotalHits for i64 and bool
russcam Mar 5, 2020
4f33571
Refactor api call construction into try_from function
russcam Mar 6, 2020
2a79413
Handle arrays that maps to string params
russcam Mar 6, 2020
8475d77
Define expand_wildcards as a collection
russcam Mar 6, 2020
0ee11ba
Extract enum creation out into local fn
russcam Mar 6, 2020
b10d05e
Fix category_id represented as string
russcam Mar 6, 2020
c0e34ba
Cehck enum options contains passed values
russcam Mar 8, 2020
f25cd30
change track_total_hits to Into<TrackTotalHits>
russcam Mar 9, 2020
6897cb3
Ensure matching path for collected API call parts
russcam Mar 9, 2020
673583d
Handle string -> integer param
russcam Mar 9, 2020
b10f3ce
fix clippy warnings
russcam Mar 9, 2020
e7b7e4c
Merge branch 'master' into enhancement/yaml-test-runner
russcam Mar 13, 2020
05a2a26
Bump runner to 7.6.1-alpha.1
russcam Mar 13, 2020
dc71349
Delete existing YAML tests when downloading
russcam Mar 13, 2020
53a4351
Initial parse skip implementation
russcam Mar 13, 2020
87309e8
fix test
russcam Mar 16, 2020
2837f5e
Enable arbitrary_precision and raw_value features
russcam Mar 16, 2020
8a67b81
Refactor test generation
russcam Mar 16, 2020
3d0d075
cargo fmt
russcam Mar 17, 2020
db4dce0
Deprecating warnings fn on Response
russcam Mar 17, 2020
9ff6c85
start of parse_match impl
russcam Mar 17, 2020
97130c5
Refactor step parsing into types
russcam Mar 18, 2020
734096b
Refactor steps into separate module
russcam Mar 20, 2020
dbb3604
Include headers in do step API calls
russcam Mar 20, 2020
ffb7d41
Implement set step
russcam Mar 24, 2020
85a814b
set values in API parts
russcam Mar 24, 2020
e61c2d9
Remove $body from beginning of body expressions
russcam Mar 25, 2020
cf54120
handle set values in API params
russcam Mar 25, 2020
9b540b0
Handle replacements in newline delimited string bodies
russcam Mar 25, 2020
d5788e6
Reset read response at each do step
russcam Mar 25, 2020
f126087
handle number params as i64
russcam Mar 25, 2020
6224062
implement length step
russcam Mar 27, 2020
f23fcab
Merge branch 'master' into enhancement/yaml-test-runner
russcam May 5, 2020
c3128b0
re-run api_generator
russcam May 5, 2020
2a4e867
Use json() and text() response functions
russcam May 5, 2020
a81996c
Handle url serialization of enum collections
russcam May 7, 2020
f9dc7f0
tidy up
russcam May 7, 2020
3451c8d
Implement catch on do steps
russcam May 7, 2020
292df79
add oss teardown
russcam May 7, 2020
ca2aae7
add xpack teardown call
russcam May 7, 2020
5adf508
complete xpack teardown
russcam May 7, 2020
e827239
Fix Match step regex
russcam May 7, 2020
9e2c991
ignore pattern whitespace in regex
russcam May 8, 2020
e165612
Determine version from ELASTICSEARCH_VERSION env var
russcam May 8, 2020
7466930
Introduce simple_logger
russcam May 8, 2020
0786bd5
generates tests only for test suite
russcam May 11, 2020
01dc846
Extract username/password for ES_TEST_SERVER
russcam May 11, 2020
11f6b6f
"set" value replacement in headers
russcam May 11, 2020
59ce058
replace println with logger calls
russcam May 11, 2020
9b479a7
introduce skip.yml to skip features and tests
russcam May 11, 2020
337c85b
Skip tests specified in skip.yml
russcam May 11, 2020
f738cb0
refactoring
russcam May 11, 2020
095ca05
Update TypeKind::None to TypeKind::Unknown(String)
russcam May 12, 2020
af14106
Fix launching oss cluster
russcam May 12, 2020
d9f0983
Implement is_true, is_false, numeric asserts
russcam May 12, 2020
ac09db3
Implement content_type on response
russcam May 12, 2020
9f983ed
Rename to json and text
russcam May 12, 2020
54fc2e7
Handle set values in numeric comparisons
russcam May 12, 2020
589e683
Add assertions in deleting indices setup
russcam May 13, 2020
99b3c86
Simplify assertions
russcam May 13, 2020
43a97a4
Handle _arbitrary_key_
russcam May 13, 2020
3e5f19e
Handle transform_and_set
russcam May 13, 2020
12a3246
Merge branch 'master' into enhancement/yaml-test-runner
russcam May 14, 2020
7a615cb
Extract method, statuscode, text and json from response
russcam May 14, 2020
16fac64
Skip ssl certificates test
russcam May 14, 2020
67b66b5
Update is_true and is_false logic to use request method
russcam May 14, 2020
f049ffc
match on all json values
russcam May 14, 2020
5a4cd40
extract regex to module
russcam May 14, 2020
b6dbd7e
Don't emit body() call for null
russcam May 14, 2020
e664cda
write i64 suffix only for values larger than i32::max_value()
russcam May 14, 2020
5d1e236
handle assertion of i64 value in test to f64 value in response
russcam May 14, 2020
d9a6d2f
Add consistent failing test and unsupported features
russcam May 14, 2020
90bdfef
Handle warnings and ignore
russcam May 15, 2020
62dd026
code format
russcam May 15, 2020
bb9fc21
introduce macros
russcam May 15, 2020
b5ea611
skip overall buckets test
russcam May 15, 2020
f50e714
assert_match and assert_regex_match macros
russcam May 15, 2020
3c2e719
Wrap numeric match branching in macro
russcam May 15, 2020
2f7e529
Add assert_length macro
russcam May 15, 2020
a7e822d
Don't assert successful response automatically
russcam May 15, 2020
66ed1a9
skip snapshot test
russcam May 15, 2020
2a38faf
handle additional i64 replace cases and simplify regex
russcam May 15, 2020
3eac83c
Replace set values and i64 in match against object and array
russcam May 15, 2020
b45a3a6
assert status code macros
russcam May 18, 2020
115795f
Generate yaml tests in tests directory
russcam May 18, 2020
eb010c0
replace backticks in regex
russcam May 18, 2020
82b7f47
Move test related components to tests/common module
russcam May 18, 2020
33068d1
read yaml into Value
russcam May 19, 2020
5d6d602
skip additional tests
russcam May 19, 2020
e6ea4f9
normalize paths across OS
russcam May 19, 2020
c486a8e
Pass expected values as serde_json::Value
russcam May 19, 2020
cf15291
warnings assertion macros
russcam May 19, 2020
c776615
emit yaml test name in log
russcam May 19, 2020
401d215
skip tests that use numeric index into Object
russcam May 19, 2020
a1024b3
clippy
russcam May 19, 2020
b7a55a4
correct test file path
russcam May 19, 2020
c0dcefe
cargo fmt
russcam May 19, 2020
a5bc0fd
macros for comparison
russcam May 20, 2020
af12cb2
stop tracking tests/mord.rs
russcam May 21, 2020
83bda33
Implement contains
russcam May 21, 2020
7c566ce
only change file names that start with numerics
russcam May 21, 2020
68e9c2e
make yaml_text_runner a binary
russcam May 21, 2020
317a397
Add license headers
russcam May 21, 2020
cfc21e3
fmt/clippy
russcam May 21, 2020
79e6046
pass skip reason
russcam May 21, 2020
ec77542
tidy up error messages
russcam May 21, 2020
95eff3a
Create a singleton client for all tests
russcam May 28, 2020
96b2627
formatting
russcam May 28, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .ci/run-elasticsearch.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ $volumes = @(
"--volume", "${volume_name}:/usr/share/elasticsearch/data"
)

if (-not ($version -contains "oss")) {
if (-not ($version -match "oss")) {
$environment += @(
"--env", "ELASTIC_PASSWORD=`"$ELASTIC_PASSWORD`"",
"--env", "xpack.license.self_generated.type=trial",
Expand All @@ -241,7 +241,7 @@ if (-not ($version -contains "oss")) {
}

$url="http://$NODE_NAME"
if (-not ($version -contains "oss")) {
if (-not ($version -match "oss")) {
$url="https://elastic:$ELASTIC_PASSWORD@$NODE_NAME"
}

Expand Down
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@ Cargo.lock
.idea
.vscode/
*.log
yaml_test_runner/
yaml_test_runner/yaml/
yaml_test_runner/tests/oss
yaml_test_runner/tests/xpack
yaml_test_runner/tests/mod.rs
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[workspace]
members = [
"api_generator",
"elasticsearch"
"elasticsearch",
"yaml_test_runner"
]
45 changes: 17 additions & 28 deletions api_generator/src/main.rs → api_generator/src/bin/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,28 @@
* specific language governing permissions and limitations
* under the License.
*/
extern crate api_generator;
extern crate dialoguer;

#[macro_use]
extern crate lazy_static;

#[macro_use]
extern crate quote;

use api_generator::{generator, rest_spec};
use dialoguer::Input;
use std::path::PathBuf;
use std::{
fs::{self, File},
io::Write,
path::Path,
};

mod api_generator;
mod error;
mod rest_spec;

fn main() {
fn main() -> Result<(), failure::Error> {
// This must be run from the src root directory, with cargo run -p api_generator
let download_dir = fs::canonicalize(PathBuf::from("./api_generator/rest_specs")).unwrap();
let generated_dir = fs::canonicalize(PathBuf::from("./elasticsearch/src/generated")).unwrap();
let last_downloaded_version = "./api_generator/last_downloaded_version";
let download_dir = fs::canonicalize(PathBuf::from("./api_generator/rest_specs"))?;
let generated_dir = fs::canonicalize(PathBuf::from("./elasticsearch/src/generated"))?;
let last_downloaded_version =
PathBuf::from("./api_generator/rest_specs/last_downloaded_version");

let mut download_specs = false;
let mut answer = String::new();
let default_branch = if Path::new(last_downloaded_version).exists() {
fs::read_to_string(last_downloaded_version).expect("Could not read branch into string")
let default_branch = if last_downloaded_version.exists() {
fs::read_to_string(&last_downloaded_version)?
} else {
String::from("master")
};
Expand Down Expand Up @@ -76,13 +68,9 @@ fn main() {
.interact()
.unwrap();

fs::remove_dir_all(&download_dir).unwrap();
rest_spec::download_specs(&branch, &download_dir);

File::create(last_downloaded_version)
.expect("failed to create last_downloaded_version file")
.write_all(branch.as_bytes())
.expect("unable to write branch to last_downloaded_version file");
fs::remove_dir_all(&download_dir)?;
rest_spec::download_specs(&branch, &download_dir)?;
File::create(&last_downloaded_version)?.write_all(branch.as_bytes())?;
}

// only offer to generate if there are downloaded specs
Expand All @@ -109,12 +97,13 @@ fn main() {
if generate_code {
// delete existing generated files if the exist
if generated_dir.exists() {
fs::remove_dir_all(&generated_dir).unwrap();
fs::remove_dir_all(&generated_dir)?;
}

fs::create_dir_all(&generated_dir).unwrap();

api_generator::generate(&branch, &download_dir, &generated_dir).unwrap();
fs::create_dir_all(&generated_dir)?;
generator::generate(&branch, &download_dir, &generated_dir)?;
}
}

Ok(())
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub mod request;
pub mod root;
pub mod url;

use crate::api_generator::TypeKind;
use crate::generator::TypeKind;
use inflector::Inflector;
use quote::Tokens;
use std::str;
Expand Down Expand Up @@ -73,7 +73,7 @@ pub fn parse_expr(input: quote::Tokens) -> syn::Expr {
}

/// Ensures that the name generated is one that is valid for Rust
fn valid_name(s: &str) -> &str {
pub fn valid_name(s: &str) -> &str {
match s {
"type" => "ty",
s => s,
Expand Down Expand Up @@ -116,7 +116,7 @@ impl GetPath for syn::Ty {
fn get_path(&self) -> &syn::Path {
match *self {
syn::Ty::Path(_, ref p) => &p,
_ => panic!("Only path types are supported."),
ref p => panic!(format!("Expected syn::Ty::Path, but found {:?}", p)),
}
}
}
Expand All @@ -138,21 +138,42 @@ impl<T: GetPath> GetIdent for T {
}

/// Gets the Ty syntax token for a TypeKind
fn typekind_to_ty(name: &str, kind: &TypeKind, required: bool) -> syn::Ty {
/// TODO: This function is serving too many purposes. Refactor it
fn typekind_to_ty(name: &str, kind: &TypeKind, required: bool, fn_arg: bool) -> syn::Ty {
let mut v = String::new();
if !required {
v.push_str("Option<");
}

let str_type = "&'b str";
match kind {
TypeKind::None => v.push_str(str_type),
TypeKind::List => v.push_str(format!("&'b [{}]", str_type).as_ref()),
TypeKind::Enum => v.push_str(name.to_pascal_case().as_str()),
TypeKind::Unknown(_) => v.push_str(str_type),
TypeKind::List => {
v.push_str("&'b [");
v.push_str(str_type);
v.push_str("]");
}
TypeKind::Enum => match name {
// opened https://github.com/elastic/elasticsearch/issues/53212
// to discuss whether this really should be a collection
"expand_wildcards" => {
// Expand wildcards should
v.push_str("&'b [");
v.push_str(name.to_pascal_case().as_str());
v.push_str("]");
}
_ => v.push_str(name.to_pascal_case().as_str()),
},
TypeKind::String => v.push_str(str_type),
TypeKind::Text => v.push_str(str_type),
TypeKind::Boolean => match name {
"track_total_hits" => v.push_str("TrackTotalHits"),
"track_total_hits" => {
if fn_arg {
v.push_str(format!("Into<{}>", name.to_pascal_case()).as_str())
} else {
v.push_str(name.to_pascal_case().as_str())
}
}
_ => v.push_str("bool"),
},
TypeKind::Number => v.push_str("i64"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
use crate::api_generator::*;
use crate::api_generator::code_gen::request::request_builder::RequestBuilder;
use crate::api_generator::code_gen::*;
use crate::generator::code_gen::request::request_builder::RequestBuilder;
use crate::generator::code_gen::*;
use crate::generator::*;
use inflector::Inflector;
use quote::Tokens;
use std::path::PathBuf;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
use crate::api_generator::*;
use crate::generator::*;
use inflector::Inflector;
use quote::Tokens;
use regex::Regex;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
use crate::api_generator::{
use crate::generator::{
code_gen, code_gen::url::enum_builder::EnumBuilder, code_gen::*, ApiEndpoint, HttpMethod, Type,
TypeKind,
};
Expand All @@ -25,7 +25,7 @@ use quote::{ToTokens, Tokens};
use reqwest::Url;
use std::path::PathBuf;
use std::{collections::BTreeMap, fs, str};
use syn::{Field, FieldValue, ImplItem};
use syn::{Field, FieldValue, ImplItem, TraitBoundModifier, TyParamBound};

/// Builder that generates the AST for a request builder struct
pub struct RequestBuilder<'a> {
Expand Down Expand Up @@ -126,7 +126,8 @@ impl<'a> RequestBuilder<'a> {
let struct_fields = endpoint_params.iter().map(|(param_name, param_type)| {
let field = Self::create_struct_field((param_name, param_type));
let field_rename = lit(param_name);
if param_type.ty == TypeKind::List {
// TODO: we special case expand_wildcards here to be a list, but this should be fixed upstream
if param_type.ty == TypeKind::List || param_name == "expand_wildcards" {
let serialize_with = lit("crate::client::serialize_coll_qs");
quote! {
#[serde(rename = #field_rename, serialize_with = #serialize_with)]
Expand Down Expand Up @@ -352,10 +353,36 @@ impl<'a> RequestBuilder<'a> {
/// Creates the AST for a builder fn for a builder impl
fn create_impl_fn(f: (&String, &Type)) -> syn::ImplItem {
let name = valid_name(&f.0).to_lowercase();
let (ty, value_ident, fn_generics) = {
let ty = typekind_to_ty(&f.0, &f.1.ty, true, true);
match ty {
syn::Ty::Path(ref _q, ref p) => {
if p.get_ident().as_ref() == "Into" {
let ty = syn::parse_type("T").unwrap();
let ident = code_gen::ident(format!("{}.into()", &name));
let ty_param = syn::TyParam {
ident: code_gen::ident("T"),
default: None,
attrs: vec![],
bounds: vec![TyParamBound::Trait(
syn::PolyTraitRef {
trait_ref: p.clone(),
bound_lifetimes: vec![],
},
TraitBoundModifier::None,
)],
};
let generics = generics(vec![], vec![ty_param]);
(ty, ident, generics)
} else {
(ty, ident(&name), generics_none())
}
}
_ => (ty, ident(&name), generics_none()),
}
};
let impl_ident = ident(&name);
let field_ident = ident(&name);
let value_ident = ident(&name);
let ty = typekind_to_ty(&f.0, &f.1.ty, true);
let doc_attr = match &f.1.description {
Some(docs) => vec![doc(docs)],
_ => vec![],
Expand All @@ -382,7 +409,7 @@ impl<'a> RequestBuilder<'a> {
output: syn::FunctionRetTy::Ty(code_gen::ty("Self")),
variadic: false,
},
generics: generics_none(),
generics: fn_generics,
},
// generates a fn body of the form
// --------
Expand All @@ -409,13 +436,11 @@ impl<'a> RequestBuilder<'a> {
enum_builder: &EnumBuilder,
accepts_nd_body: bool,
) -> Tokens {
// TODO: lazy_static! for this?
let mut common_fields: Vec<Field> = common_params
.iter()
.map(Self::create_struct_field)
.collect();

// TODO: lazy_static! for this?
let mut common_builder_fns: Vec<ImplItem> =
common_params.iter().map(Self::create_impl_fn).collect();

Expand Down Expand Up @@ -667,7 +692,7 @@ impl<'a> RequestBuilder<'a> {
ident: Some(ident(valid_name(&f.0).to_lowercase())),
vis: syn::Visibility::Inherited,
attrs: vec![],
ty: typekind_to_ty(&f.0, &f.1.ty, false),
ty: typekind_to_ty(&f.0, &f.1.ty, false, false),
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
use crate::api_generator::*;
use crate::api_generator::code_gen::request::request_builder::RequestBuilder;
use crate::api_generator::code_gen::*;
use crate::generator::code_gen::request::request_builder::RequestBuilder;
use crate::generator::code_gen::*;
use crate::generator::*;
use inflector::Inflector;
use quote::Tokens;
use std::path::PathBuf;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
use crate::api_generator::code_gen::url::url_builder::{IntoExpr, UrlBuilder};
use crate::api_generator::{code_gen::*, ApiEndpoint, Path};
use crate::generator::code_gen::url::url_builder::{IntoExpr, UrlBuilder};
use crate::generator::{code_gen::*, ApiEndpoint, Path};
use inflector::Inflector;

/// Builder for request url parts enum
Expand Down Expand Up @@ -139,7 +139,7 @@ impl<'a> EnumBuilder<'a> {
ident: None,
vis: syn::Visibility::Inherited,
attrs: vec![],
ty: typekind_to_ty(p, ty, true),
ty: typekind_to_ty(p, ty, true, false),
}
})
.collect(),
Expand Down Expand Up @@ -306,15 +306,16 @@ mod tests {
#![cfg_attr(rustfmt, rustfmt_skip)]

use super::*;
use crate::api_generator::{Url, Path, HttpMethod, Body, Deprecated, Type, TypeKind, Documentation, ast_eq};
use crate::generator::{Url, Path, HttpMethod, Body, Deprecated, Type, TypeKind, Documentation, ast_eq};
use std::collections::BTreeMap;
use crate::api_generator::code_gen::url::url_builder::PathString;
use crate::generator::code_gen::url::url_builder::PathString;

#[test]
fn generate_parts_enum_from_endpoint() {
let endpoint = (
"search".to_string(),
ApiEndpoint {
full_name: Some("search".to_string()),
documentation: Documentation {
description: None,
url: None,
Expand Down
Loading