Skip to content

Commit

Permalink
Merge pull request #1284 from YuliaProkopovych/query-tests
Browse files Browse the repository at this point in the history
READY(unitore) : Add tests for query_execute
  • Loading branch information
Wandalen authored Apr 25, 2024
2 parents 9bbdd13 + 4395068 commit d40e335
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 15 deletions.
6 changes: 3 additions & 3 deletions module/move/unitore/src/action/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@
// aaa : fixed
use crate::*;
use gluesql::core::executor::Payload;
use sled_adapter::{ FeedStorage, Store };
use sled_adapter::Store;
use action::Report;
use error_tools::Result;

/// Execute query specified in query string.
pub async fn query_execute
(
mut storage : FeedStorage< gluesql::sled_storage::SledStorage >,
mut storage : impl Store,
query_str : String,
) -> Result< impl Report >
{
storage.execute_query( query_str ).await
storage.query_execute( query_str ).await
}

const EMPTY_CELL : &'static str = "";
Expand Down
4 changes: 2 additions & 2 deletions module/move/unitore/src/sled_adapter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,13 @@ impl FeedStorage< SledStorage >
pub trait Store
{
/// Execute custom query passed as String.
async fn execute_query( &mut self, query : String ) -> Result< QueryReport >;
async fn query_execute( &mut self, query : String ) -> Result< QueryReport >;
}

#[ async_trait::async_trait( ?Send ) ]
impl< S : GStore + GStoreMut + Send > Store for FeedStorage< S >
{
async fn execute_query( &mut self, query : String ) -> Result< QueryReport >
async fn query_execute( &mut self, query : String ) -> Result< QueryReport >
{
let glue = &mut *self.0.lock().await;
let payloads = glue.execute( &query ).await.context( "Failed to execute query" )?;
Expand Down
5 changes: 2 additions & 3 deletions module/move/unitore/tests/config_add.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,8 @@ async fn config_add() -> Result< () >
.collect::< Vec< _ > >()
;

assert!( feeds_links.len() == 2 );
assert!( feeds_links.contains( &format!( "https://feeds.bbci.co.uk/news/world/rss.xml" ) ) );
assert!( feeds_links.contains( &format!( "https://rss.nytimes.com/services/xml/rss/nyt/World.xml" ) ) );
assert!( feeds_links.len() == 1 );
assert!( feeds_links.contains( &format!( "https://www.nasa.gov/feed/" ) ) );

Ok( () )
}
4 changes: 2 additions & 2 deletions module/move/unitore/tests/config_delete.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::path::PathBuf;
use gluesql::
{
sled_storage::sled::Config,
Expand All @@ -15,7 +14,8 @@ use error_tools::Result;
#[ tokio::test ]
async fn config_delete() -> Result< () >
{
let path = PathBuf::from( "./tests/fixtures/test_config.toml" );

let path = std::path::PathBuf::from( "./tests/fixtures/test_config.toml" );
let temp_path = proper_path_tools::path::unique_folder_name().unwrap();

let config = Config::default()
Expand Down
6 changes: 1 addition & 5 deletions module/move/unitore/tests/fixtures/test_config.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
[[config]]
update_period = "1min"
link = "https://feeds.bbci.co.uk/news/world/rss.xml"

[[config]]
update_period = "1min"
link = "https://rss.nytimes.com/services/xml/rss/nyt/World.xml"
link = "https://www.nasa.gov/feed/"
187 changes: 187 additions & 0 deletions module/move/unitore/tests/query_execute.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
use feed_rs::parser as feed_parser;
use unitore::
{
feed_config::SubscriptionConfig,
sled_adapter::{ FeedStorage, Store, MockStore },
entity::{ config::ConfigStore, feed::FeedStore },
action::{ query::{ self, QueryReport }, config },
command::query::QueryCommand,
};
use gluesql::
{
prelude::{ Payload::{ self, Select }, Value::{ Str, Timestamp } },
core::chrono::NaiveDateTime,
sled_storage::sled,
};
use wca::{ VerifiedCommand, CommandsAggregator, Type, Parser, Dictionary, Verifier, Executor };
use error_tools::Result;
use mockall::predicate;
use std::path::PathBuf;

#[ test ]
fn query_execute() -> Result< () >
{
// init parser
let parser = Parser;

// init converter
let dictionary = &Dictionary::former()
.command( QueryCommand::execute()? )
.form()
;
let verifier = Verifier;

// init executor
let executor = Executor::former().form();
let args = vec![ ".query.execute".to_string(), "SELECT title FROM frame".into() ];
let raw_program = parser.parse( args ).unwrap();
let grammar_program = verifier.to_program( dictionary, raw_program ).unwrap();

let res = executor.program( dictionary, grammar_program );
assert!( res.is_ok() );

// test action
let rt = tokio::runtime::Runtime::new()?;
let ca = CommandsAggregator::former()
.command( "query.execute" )
.hint( "hint" )
.long_hint( "long_hint" )
.subject().hint( "SQL query" ).kind( Type::String ).optional( false ).end()
.routine( move | o : VerifiedCommand |
{
let mut f_store = MockStore::new();
f_store
.expect_query_execute()
.with( predicate::eq( "SELECT title FROM frame".to_string() ) )
.times( 1 )
.returning( | _ | Ok( QueryReport
(
vec!
[
Select { labels : vec![ Str( "title".to_string() ).into() ], rows : Vec::new() }
]
)
) )
;
_ = rt.block_on( async move
{
let query_arg = o.args
.get_owned::< String >( 0 )
;

let query_str = query_arg.unwrap();
query::query_execute( f_store, query_str ).await
} );
} )
.end()
.perform();
let entries = ca.perform( vec![ ".query.execute".to_string(), "SELECT title FROM frame".into() ] );
assert!( entries.is_ok() );
Ok( () )
}

#[ tokio::test ]
async fn query_feeds() -> Result< () >
{
let path = PathBuf::from( "./tests/fixtures/test_config.toml" );
let temp_path = proper_path_tools::path::unique_folder_name().unwrap();

let config = sled::Config::default()
.path( format!( "./{}", temp_path ) )
.temporary( true )
;

let mut feed_storage = FeedStorage::init_storage( &config ).await?;
config::config_add( feed_storage.clone(), &path ).await?;

let entries = feed_storage.query_execute( "SELECT link FROM feed".to_string() ).await?;

assert!( !entries.0.is_empty() );
if let Select { labels, rows } = &entries.0[ 0 ]
{
assert_eq!( labels.len(), 1 );
assert_eq!( labels[ 0 ], "link" );
assert_eq!( rows.len(), 1 );
}
else
{
assert!( false )
}

Ok( () )
}

#[ tokio::test ]
async fn query_frames() -> Result< () >
{
let temp_path = proper_path_tools::path::unique_folder_name().unwrap();

let config = sled::Config::default()
.path( format!( "./{}", temp_path ) )
.temporary( true )
;

let mut feed_storage = FeedStorage::init_storage( &config ).await?;
let feed_config = SubscriptionConfig
{
update_period : std::time::Duration::from_secs( 1000 ),
link : url::Url::parse( "https://www.nasa.gov/feed/" )?,
};
let mut feeds = Vec::new();

let feed = feed_parser::parse( include_str!("./fixtures/plain_feed.xml").as_bytes() )?;
feeds.push( ( feed, feed_config.update_period.clone(), feed_config.link.clone() ) );
feed_storage.feeds_process( feeds ).await?;

let entries = feed_storage.query_execute( "SELECT title, published FROM frame ORDER BY published".to_string() ).await?;

assert!( !entries.0.is_empty() );

if let Select { labels, rows } = &entries.0[ 0 ]
{
assert_eq!( labels.len(), 2 );
assert!( labels.contains( &String::from( "title" ) ) );
assert!( labels.contains( &String::from( "published" ) ) );
assert_eq!( rows.len(), 10 );
assert_eq!( rows[ 0 ][ 0 ], Str( "8 Must-Have NASA Resources for Science Teachers in 2024".to_string() ) );
assert_eq!( rows[ 0 ][ 1 ], Timestamp( NaiveDateTime::parse_from_str( "13 Mar 2024 16:31:23", "%d %b %Y %H:%M:%S" )? ) );
assert_eq!( rows[ 9 ][ 0 ], Str( "Icing Cloud Characterization Engineer Emily Timko".to_string() ) );
assert_eq!( rows[ 9 ][ 1 ], Timestamp( NaiveDateTime::parse_from_str( "14 Mar 2024 14:27:52", "%d %b %Y %H:%M:%S" )? ) );
}
else
{
assert!( false )
}

Ok( () )
}

#[ tokio::test ]
async fn query_configs() -> Result< () >
{
let path = PathBuf::from( "./tests/fixtures/test_config.toml" );
let temp_path = proper_path_tools::path::unique_folder_name().unwrap();

let config = sled::Config::default()
.path( format!( "./{}", temp_path ) )
.temporary( true )
;

let mut feed_storage = FeedStorage::init_storage( &config ).await?;
let _res = feed_storage.query_execute( format!( "INSERT INTO config VALUES ('{}') ", path.to_string_lossy().to_string() ) ).await?;
let res = feed_storage.config_list().await?;

if let Payload::Select{ labels, rows } = &res
{
assert_eq!( labels.len(), 1 );
assert!( labels.contains( &String::from( "path" ) ) );
assert_eq!( rows.len(), 1 );
assert_eq!( rows[ 0 ][ 0 ], Str( path.to_string_lossy().to_string() ) );
}
else
{
assert!( false );
}

Ok( () )
}

0 comments on commit d40e335

Please sign in to comment.