Skip to content

Commit

Permalink
Merge pull request #9 from rbtcollins/testharness
Browse files Browse the repository at this point in the history
More test interaction work
  • Loading branch information
anguslees authored Mar 19, 2019
2 parents efac094 + 3519e31 commit 602437c
Show file tree
Hide file tree
Showing 4 changed files with 300 additions and 110 deletions.
259 changes: 150 additions & 109 deletions examples/log2har.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ fn parse_log(input: &str) -> Result<String, Error> {
// the iterator must succeed given the definition of file - otherwise parse fails.
let log = LogParser::parse(Rule::file, &input)?.next().unwrap();
let mut result = String::new();
let mut entries: Vec<v1_3::Entries> = Vec::new();
for record in log.into_inner() {
match record.as_rule() {
Rule::log_entry => {
Expand Down Expand Up @@ -216,12 +217,26 @@ fn parse_log(input: &str) -> Result<String, Error> {
e => Err(format_err!("Unexpected parse rule 2 encountered {:?}", e))?,
}
}
result.push_str(&format!("{}\n", serde_json::to_string_pretty(&entry)?));
entries.push(entry);
}
Rule::EOI => (),
e => Err(format_err!("Unexpected parse rule 1 encountered {:?}", e))?,
}
}
let har_log = har::Har {
log: har::Spec::V1_3(v1_3::Log {
browser: None,
creator: v1_3::Creator {
name: "kubernetes-rs".to_string(),
version: "0".to_string(),
comment: None,
},
pages: None,
entries: entries,
comment: None,
}),
};
result.push_str(&format!("{}\n", serde_json::to_string_pretty(&har_log)?));
Ok(result)
}

Expand Down Expand Up @@ -300,62 +315,75 @@ I0225 20:16:03.147299 14148 request.go:942] Response Body: {
}
"#;
let expected = r#"{
"pageref": null,
"startedDateTime": "",
"time": 0,
"request": {
"method": "GET",
"url": "https://localhost:6445/version?timeout=32s",
"httpVersion": "unknown",
"cookies": [],
"headers": [
{
"name": "Accept",
"value": "application/json, */*"
},
{
"name": "User-Agent",
"value": "kubectl/v1.13.0 (windows/amd64) kubernetes/ddf47ac"
}
],
"queryString": [],
"headersSize": -1,
"bodySize": -1
},
"response": {
"status": -1,
"statusText": "",
"httpVersion": "unknown",
"cookies": [],
"headers": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Content-Length",
"value": "263"
},
"log": {
"version": "1.3",
"creator": {
"name": "kubernetes-rs",
"version": "0"
},
"browser": null,
"pages": null,
"entries": [
{
"name": "Date",
"value": "Thu, 21 Feb 2019 21:04:01 GMT"
"pageref": null,
"startedDateTime": "",
"time": 0,
"request": {
"method": "GET",
"url": "https://localhost:6445/version?timeout=32s",
"httpVersion": "unknown",
"cookies": [],
"headers": [
{
"name": "Accept",
"value": "application/json, */*"
},
{
"name": "User-Agent",
"value": "kubectl/v1.13.0 (windows/amd64) kubernetes/ddf47ac"
}
],
"queryString": [],
"headersSize": -1,
"bodySize": -1
},
"response": {
"status": -1,
"statusText": "",
"httpVersion": "unknown",
"cookies": [],
"headers": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Content-Length",
"value": "263"
},
{
"name": "Date",
"value": "Thu, 21 Feb 2019 21:04:01 GMT"
}
],
"content": {
"size": -1,
"mimeType": "",
"text": "ewogICJtYWpvciI6ICIxIiwKICAibWlub3IiOiAiMTMiLAogICJnaXRWZXJzaW9uIjogInYxLjEzLjAiLAogICJnaXRDb21taXQiOiAiZGRmNDdhYzEzYzFhOTQ4M2VhMDM1YTc5Y2Q3YzEwMDA1ZmYyMWE2ZCIsCiAgImdpdFRyZWVTdGF0ZSI6ICJjbGVhbiIsCiAgImJ1aWxkRGF0ZSI6ICIyMDE4LTEyLTAzVDIwOjU2OjEyWiIsCiAgImdvVmVyc2lvbiI6ICJnbzEuMTEuMiIsCiAgImNvbXBpbGVyIjogImdjIiwKICAicGxhdGZvcm0iOiAibGludXgvYW1kNjQiCn0K",
"encoding": "base64"
},
"redirectURL": "",
"headersSize": -1,
"bodySize": -1
},
"cache": {},
"timings": {
"send": -1,
"wait": -1,
"receive": -1
}
}
],
"content": {
"size": -1,
"mimeType": "",
"text": "ewogICJtYWpvciI6ICIxIiwKICAibWlub3IiOiAiMTMiLAogICJnaXRWZXJzaW9uIjogInYxLjEzLjAiLAogICJnaXRDb21taXQiOiAiZGRmNDdhYzEzYzFhOTQ4M2VhMDM1YTc5Y2Q3YzEwMDA1ZmYyMWE2ZCIsCiAgImdpdFRyZWVTdGF0ZSI6ICJjbGVhbiIsCiAgImJ1aWxkRGF0ZSI6ICIyMDE4LTEyLTAzVDIwOjU2OjEyWiIsCiAgImdvVmVyc2lvbiI6ICJnbzEuMTEuMiIsCiAgImNvbXBpbGVyIjogImdjIiwKICAicGxhdGZvcm0iOiAibGludXgvYW1kNjQiCn0K",
"encoding": "base64"
},
"redirectURL": "",
"headersSize": -1,
"bodySize": -1
},
"cache": {},
"timings": {
"send": -1,
"wait": -1,
"receive": -1
]
}
}
"#;
Expand Down Expand Up @@ -384,62 +412,75 @@ I0219 14:38:39.153335 13292 request.go:942] Response Body: {
}
"#;
let expected = r#"{
"pageref": null,
"startedDateTime": "",
"time": 0,
"request": {
"method": "GET",
"url": "https://localhost:6445/api/v1/namespaces?limit=500",
"httpVersion": "unknown",
"cookies": [],
"headers": [
{
"name": "User-Agent",
"value": "kubectl/v1.13.0 (windows/amd64) kubernetes/ddf47ac"
},
{
"name": "Accept",
"value": "application/json;as=Table;v=v1beta1;g=meta.k8s.io, application/json"
}
],
"queryString": [],
"headersSize": -1,
"bodySize": -1
},
"response": {
"status": -1,
"statusText": "",
"httpVersion": "unknown",
"cookies": [],
"headers": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Content-Length",
"value": "263"
},
"log": {
"version": "1.3",
"creator": {
"name": "kubernetes-rs",
"version": "0"
},
"browser": null,
"pages": null,
"entries": [
{
"name": "Date",
"value": "Sun, 17 Feb 2019 15:21:36 GMT"
"pageref": null,
"startedDateTime": "",
"time": 0,
"request": {
"method": "GET",
"url": "https://localhost:6445/api/v1/namespaces?limit=500",
"httpVersion": "unknown",
"cookies": [],
"headers": [
{
"name": "User-Agent",
"value": "kubectl/v1.13.0 (windows/amd64) kubernetes/ddf47ac"
},
{
"name": "Accept",
"value": "application/json;as=Table;v=v1beta1;g=meta.k8s.io, application/json"
}
],
"queryString": [],
"headersSize": -1,
"bodySize": -1
},
"response": {
"status": -1,
"statusText": "",
"httpVersion": "unknown",
"cookies": [],
"headers": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Content-Length",
"value": "263"
},
{
"name": "Date",
"value": "Sun, 17 Feb 2019 15:21:36 GMT"
}
],
"content": {
"size": -1,
"mimeType": "",
"text": "ewogICJtYWpvciI6ICIxIiwKICAibWlub3IiOiAiMTMiLAogICJnaXRWZXJzaW9uIjogInYxLjEzLjAiLAogICJnaXRDb21taXQiOiAiZGRmNDdhYzEzYzFhOTQ4M2VhMDM1YTc5Y2Q3YzEwMDA1ZmYyMWE2ZCIsCiAgImdpdFRyZWVTdGF0ZSI6ICJjbGVhbiIsCiAgImJ1aWxkRGF0ZSI6ICIyMDE4LTEyLTAzVDIwOjU2OjEyWiIsCiAgImdvVmVyc2lvbiI6ICJnbzEuMTEuMiIsCiAgImNvbXBpbGVyIjogImdjIiwKICAicGxhdGZvcm0iOiAibGludXgvYW1kNjQiCn0K",
"encoding": "base64"
},
"redirectURL": "",
"headersSize": -1,
"bodySize": -1
},
"cache": {},
"timings": {
"send": -1,
"wait": -1,
"receive": -1
}
}
],
"content": {
"size": -1,
"mimeType": "",
"text": "ewogICJtYWpvciI6ICIxIiwKICAibWlub3IiOiAiMTMiLAogICJnaXRWZXJzaW9uIjogInYxLjEzLjAiLAogICJnaXRDb21taXQiOiAiZGRmNDdhYzEzYzFhOTQ4M2VhMDM1YTc5Y2Q3YzEwMDA1ZmYyMWE2ZCIsCiAgImdpdFRyZWVTdGF0ZSI6ICJjbGVhbiIsCiAgImJ1aWxkRGF0ZSI6ICIyMDE4LTEyLTAzVDIwOjU2OjEyWiIsCiAgImdvVmVyc2lvbiI6ICJnbzEuMTEuMiIsCiAgImNvbXBpbGVyIjogImdjIiwKICAicGxhdGZvcm0iOiAibGludXgvYW1kNjQiCn0K",
"encoding": "base64"
},
"redirectURL": "",
"headersSize": -1,
"bodySize": -1
},
"cache": {},
"timings": {
"send": -1,
"wait": -1,
"receive": -1
]
}
}
"#;
Expand Down
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
#[cfg(test)]
extern crate failure;

#[cfg(test)]
mod tests;
74 changes: 74 additions & 0 deletions src/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use failure::{err_msg, Error};
use har;
use serde_json::Value;

use ::kubernetes_api::core::v1::NamespaceList;

fn entries(ahar: &har::Har) -> Result<&Vec<har::v1_3::Entries>, Error> {
match &ahar.log {
har::Spec::V1_3(log) => Ok(&log.entries),
_ => Err(err_msg("unexpected har version")),
}
}

fn response(entry: &har::v1_3::Entries) -> Result<String, Error> {
// https://github.com/rust-lang/rust/issues/46871
// let body = &entry.response.content.text?;
let body = entry
.response
.content
.text
.as_ref()
.ok_or(err_msg("no response body"))?;
Ok(match &entry.response.content.encoding {
None => body.clone(),
Some(enc) if enc == "base64" => String::from_utf8(base64::decode(&body)?)?,
Some(enc) => Err(err_msg(format!("unknown encoding {}", enc)))?,
})
}

#[test]
fn test_namespace_har() -> Result<(), Error> {
// This is not generalised. We should aim to make this model driven and fully generalised, but EFUTURE.
// Load the HAR
// HAR errors are awkwardly incompatibly... feel free to whinge,
// but even map_err was throwing from::From failures - I think due to har's Result wrapper.
let har = match har::from_path("testdata/traces/json/get-namespaces.har") {
Ok(something) => Ok(something),
Err(e) => Err(err_msg(format!("{}", e))),
}?;
for entry in entries(&har)? {
println!("url {:?}", entry.request.url);
// XXX todos:
// Check that the GVK url route is correct - route that URL and match back to the GVK or vice versa.
// cross check the self link?
// its a get, no payload upload verification
// verify the GET options from the URL are understood - do we have a parser for those ?

// parse the response by its expected type
let response_str = response(entry)?;
println!("response {}", response_str);
let typed: NamespaceList = serde_json::from_str(&response_str)?;
println!("list {:?}", typed);
println!("list-to-json {}", serde_json::to_string_pretty(&typed)?);
// reserialise the response to JSON, bounce it back through Value to eliminate the *ordering* in the output imposed by the use of structured types.
let typed_json = serde_json::to_string_pretty(&serde_json::from_str::<Value>(
&serde_json::to_string_pretty(&typed)?,
)?)?;
// let typed_interim: Value = serde_json::from_str(&typed_j)
// compare the resulting JSON
// canonicalise the reference JSON to avoid over-time library output variations.
let interim: Value = serde_json::from_str(&response_str)?;
let canonical = serde_json::to_string_pretty(&interim)?;
println!("{}", canonical);
println!("{}", typed_json);
// XXX: should be eq, but need to:
// - fix Pods kind in output
// - remove extra apiVersion and kind etc
// - implement omitEmpty
// XXX or alternatively have a different round trip verification approach
assert_ne!(canonical, typed_json);
// compare equal.
}
Ok(())
}
Loading

0 comments on commit 602437c

Please sign in to comment.