blob: 7a697249a917f6f0938c7b97edf2be5d773b012c [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::{
io::Write,
path::PathBuf,
process::{Command, Stdio},
};
pub mod schema;
pub trait Monorail {
fn create_issue(&mut self, request: schema::MakeIssueRequest) -> Result<schema::Issue>;
fn update_issues(&mut self, request: schema::ModifyIssuesRequest) -> Result<()>;
fn list_component_defs(
&mut self,
request: schema::ListComponentDefsRequest,
) -> Result<schema::ListComponentDefsResponse>;
}
pub struct Mock {
next_issue_id: usize,
log_api: bool,
prpc: Option<Prpc>,
}
impl Mock {
pub fn new(log_api: bool, prpc: Option<Prpc>) -> Self {
Self { next_issue_id: 0, log_api, prpc }
}
}
impl Monorail for Mock {
fn create_issue(&mut self, request: schema::MakeIssueRequest) -> Result<schema::Issue> {
if self.log_api {
println!("[mock] Filing issue {}:\n{:#?}", self.next_issue_id, request);
}
let name = format!("{}/issues/{}", request.parent, self.next_issue_id);
self.next_issue_id += 1;
Ok(schema::Issue { name: Some(name), ..request.issue })
}
fn update_issues(&mut self, request: schema::ModifyIssuesRequest) -> Result<()> {
if self.log_api {
println!("[mock] Updating issues:\n{:#?}", request);
}
Ok(())
}
fn list_component_defs(
&mut self,
request: schema::ListComponentDefsRequest,
) -> Result<schema::ListComponentDefsResponse> {
if self.log_api {
println!("[mock] Listing component defs:\n{:#?}", request);
}
if let Some(ref mut prpc) = self.prpc {
prpc.list_component_defs(request)
} else {
Ok(schema::ListComponentDefsResponse {
component_defs: Vec::new(),
next_page_token: None,
})
}
}
}
pub struct Prpc {
binary_path: PathBuf,
api_server: String,
}
impl Prpc {
pub fn new(binary_path: PathBuf, api_server: String) -> Self {
Self { binary_path, api_server }
}
pub fn call<I, O>(&self, name: &str, input: &I) -> Result<O>
where
I: Serialize,
O: for<'de> Deserialize<'de>,
{
let mut prpc = Command::new(&self.binary_path)
.args(["call", "-use-id-token", &self.api_server, name])
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.spawn()?;
let prpc_stdin = prpc.stdin.as_mut().unwrap();
let body = serde_json::to_string(input)?;
prpc_stdin.write_all(body.as_bytes())?;
let output = prpc.wait_with_output()?;
Ok(serde_json::from_slice(&output.stdout)?)
}
}
impl Monorail for Prpc {
fn create_issue(&mut self, request: schema::MakeIssueRequest) -> Result<schema::Issue> {
self.call("monorail.v3.Issues.MakeIssue", &request)
}
fn update_issues(&mut self, request: schema::ModifyIssuesRequest) -> Result<()> {
self.call("monorail.v3.Issues.ModifyIssues", &request)
}
fn list_component_defs(
&mut self,
request: schema::ListComponentDefsRequest,
) -> Result<schema::ListComponentDefsResponse> {
self.call("monorail.v3.Projects.ListComponentDefs", &request)
}
}