Skip to content

Commit

Permalink
move json to md
Browse files Browse the repository at this point in the history
  • Loading branch information
ssddOnTop committed Aug 26, 2024
1 parent f66fc89 commit 0f955c0
Show file tree
Hide file tree
Showing 6 changed files with 326 additions and 19 deletions.
3 changes: 3 additions & 0 deletions src/cli/generator/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ pub struct Config<Status = UnResolved> {
#[serde(skip_serializing_if = "Option::is_none")]
pub preset: Option<PresetConfig>,
pub schema: Schema,
#[serde(default, skip_serializing_if = "TemplateString::is_empty")]
pub secret: TemplateString,
#[serde(skip_serializing_if = "Option::is_none")]
pub llm: Option<LLMConfig>,
}
Expand Down Expand Up @@ -293,6 +295,7 @@ impl Config {
output,
schema: self.schema,
preset: self.preset,
secret: self.secret,
llm,
})
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
```json @config
{
"inputs": [
{
Expand Down Expand Up @@ -63,3 +64,4 @@
"query": "Query"
}
}
```
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
```json @config
{
"inputs": [
{
Expand All @@ -8,7 +9,7 @@
},
{
"proto": {
"src": "../../../../../../tailcall-fixtures/fixtures/protobuf/news.proto"
"src": "tailcall-fixtures/fixtures/protobuf/news.proto"
}
}
],
Expand All @@ -26,3 +27,4 @@
"query": "Query"
}
}
```
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
```json @config
{
"inputs": [
{
Expand Down Expand Up @@ -81,3 +82,4 @@
"query": "Query"
}
}
```
202 changes: 184 additions & 18 deletions tests/cli/gen.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,166 @@
mod parser;

pub mod cacache_manager {
use std::io::{Read, Write};
use std::path::PathBuf;

use flate2::write::GzEncoder;
use flate2::Compression;
use http_cache_reqwest::{CacheManager, HttpResponse};
use http_cache_semantics::CachePolicy;
use serde::{Deserialize, Serialize};

pub type BoxError = Box<dyn std::error::Error + Send + Sync>;
pub type Result<T> = std::result::Result<T, BoxError>;

pub struct CaCacheManager {
path: PathBuf,
}

#[derive(Clone, Deserialize, Serialize)]
pub struct Store {
response: HttpResponse,
policy: CachePolicy,
}

impl Default for CaCacheManager {
fn default() -> Self {
Self { path: PathBuf::from("./.cache") }
}
}

#[async_trait::async_trait]
impl CacheManager for CaCacheManager {
async fn put(
&self,
cache_key: String,
response: HttpResponse,
policy: CachePolicy,
) -> Result<HttpResponse> {
let data = Store { response: response.clone(), policy };
let bytes = bincode::serialize(&data)?;

let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
encoder.write_all(&bytes)?;
let compressed_bytes = encoder.finish()?;

cacache::write(&self.path, cache_key, compressed_bytes).await?;
Ok(response)
}

async fn get(&self, cache_key: &str) -> Result<Option<(HttpResponse, CachePolicy)>> {
match cacache::read(&self.path, cache_key).await {
Ok(compressed_data) => {
let mut decoder = flate2::read::GzDecoder::new(compressed_data.as_slice());
let mut serialized_data = Vec::new();
decoder.read_to_end(&mut serialized_data)?;
let store: Store = bincode::deserialize(&serialized_data)?;
Ok(Some((store.response, store.policy)))
}
Err(_) => Ok(None),
}
}

async fn delete(&self, cache_key: &str) -> Result<()> {
Ok(cacache::remove(&self.path, cache_key).await?)
}
}
}

pub mod file {
use std::collections::HashMap;
use std::sync::Arc;

use async_trait::async_trait;
use tailcall::core::FileIO;
use tokio::sync::RwLock;

#[derive(Clone, Default)]
pub struct NativeFileTest(Arc<RwLock<HashMap<String, String>>>);
#[async_trait]
impl FileIO for NativeFileTest {
async fn write<'a>(&'a self, path: &'a str, content: &'a [u8]) -> anyhow::Result<()> {
self.0.write().await.insert(
path.to_string(),
String::from_utf8_lossy(content).to_string(),
);
Ok(())
}

async fn read<'a>(&'a self, path: &'a str) -> anyhow::Result<String> {
let val = if let Some(val) = self.0.read().await.get(path).cloned() {
val
} else {
std::fs::read_to_string(path)?
};
Ok(val)
}
}
}

pub mod http {
use anyhow::Result;
use http_cache_reqwest::{Cache, CacheMode, HttpCache, HttpCacheOptions};
use hyper::body::Bytes;
use reqwest::Client;
use reqwest_middleware::{ClientBuilder, ClientWithMiddleware};
use tailcall::core::http::Response;
use tailcall::core::HttpIO;

use super::cacache_manager::CaCacheManager;

#[derive(Clone)]
pub struct NativeHttpTest {
client: ClientWithMiddleware,
}

impl Default for NativeHttpTest {
fn default() -> Self {
let mut client = ClientBuilder::new(Client::new());
client = client.with(Cache(HttpCache {
mode: CacheMode::ForceCache,
manager: CaCacheManager::default(),
options: HttpCacheOptions::default(),
}));
Self { client: client.build() }
}
}

#[async_trait::async_trait]
impl HttpIO for NativeHttpTest {
#[allow(clippy::blocks_in_conditions)]
async fn execute(&self, request: reqwest::Request) -> Result<Response<Bytes>> {
let response = self.client.execute(request).await;
Ok(Response::from_reqwest(
response?
.error_for_status()
.map_err(|err| err.without_url())?,
)
.await?)
}
}
}
pub mod env {
use std::borrow::Cow;
use std::collections::HashMap;

use tailcall::core::EnvIO;

#[derive(Clone)]
pub struct Env(pub HashMap<String, String>);

impl EnvIO for Env {
fn get(&self, key: &str) -> Option<Cow<'_, str>> {
self.0.get(key).map(Cow::from)
}
}
}

pub mod test {
use std::path::Path;

use crate::parser::ExecutionSpec;

mod cacache_manager {
use std::io::{Read, Write};
use std::path::PathBuf;
Expand Down Expand Up @@ -120,25 +280,31 @@ pub mod test {
use tailcall::core::config::{self, ConfigModule};
use tailcall::core::generator::Generator as ConfigGenerator;
use tailcall::core::valid::{ValidateInto, Validator};
use tokio::runtime::Runtime;

use super::http::NativeHttpTest;
use crate::env::Env;
use crate::parser::{ExecutionSpec, IO};

pub fn run_config_generator_spec(path: &Path) -> datatest_stable::Result<()> {
let path = path.to_path_buf();
let runtime = Runtime::new().unwrap();
runtime.block_on(async move {
run_test(&path.to_string_lossy()).await?;
Ok(())
})
}
pub async fn run_test(original_path: &Path, spec: ExecutionSpec) -> anyhow::Result<()> {
let snapshot_name = original_path.to_string_lossy().to_string();

let IO { fs, paths } = spec.configs.into_io().await;
let path = paths.first().unwrap().as_str();

async fn run_test(path: &str) -> anyhow::Result<()> {
let mut runtime = tailcall::cli::runtime::init(&Blueprint::default());
runtime.http = Arc::new(NativeHttpTest::default());
runtime.file = Arc::new(fs);
if let Some(env) = spec.env {
runtime.env = Arc::new(Env(env))
}

let generator = Generator::new(path, runtime);
let config = generator.read().await?;
if spec.debug_assert_config {
insta::assert_debug_snapshot!(snapshot_name, config);
return Ok(());
}

let query_type = config.schema.query.clone().unwrap_or("Query".into());
let mutation_type_name = config.schema.mutation.clone();
let preset: config::transformer::Preset = config
Expand All @@ -164,11 +330,11 @@ pub mod test {

let config = ConfigModule::from(base_config);

insta::assert_snapshot!(path, config.to_sdl());
insta::assert_snapshot!(snapshot_name, config.to_sdl());
Ok(())
}
}
pub fn test_generator(path: &Path) -> datatest_stable::Result<()> {
async fn test_generator(path: &Path) -> datatest_stable::Result<()> {
if let Some(extension) = path.extension() {
if extension == "json"
&& path
Expand All @@ -177,15 +343,15 @@ pub mod test {
.map(|v| v.starts_with("gen"))
.unwrap_or_default()
{
let _ = generator_spec::run_config_generator_spec(path);
let spec = ExecutionSpec::from_source(path, std::fs::read_to_string(path)?)?;
generator_spec::run_test(path, spec).await?;
}
}
Ok(())
}
pub fn run(path: &Path) -> datatest_stable::Result<()> {
tokio_test::block_on(test_generator(path))
}
}

datatest_stable::harness!(
test::test_generator,
"tests/cli/fixtures/generator",
r"^.*\.json"
);
datatest_stable::harness!(test::run, "tests/cli/fixtures/generator", r"^.*\.md");
Loading

0 comments on commit 0f955c0

Please sign in to comment.