<commit_before>use juniper::{graphql_value, RootNode, Value};

#[derive(juniper::GraphQLEnum)]
enum UserKind {
    Admin,
    User,
    Guest,
}

struct User {
    id: u64,
    name: String,
    kind: UserKind,
}

#[juniper::graphql_object]
impl User {
    async fn name(&self) -> &str {
        &self.name
    }

    async fn friends(&self) -> Vec<User> {
        (0..10)
            .map(|index| User {
                id: index,
                name: format!("user{}", index),
                kind: UserKind::User,
            })
            .collect()
    }

    async fn kind(&self) -> &UserKind {
        &self.kind
    }

    async fn delayed() -> bool {
        tokio::time::delay_for(std::time::Duration::from_millis(100)).await;
        true
    }
}

struct Query;

#[juniper::graphql_object]
impl Query {
    fn field_sync(&self) -> &'static str {
        "field_sync"
    }

    async fn field_async_plain() -> String {
        "field_async_plain".to_string()
    }

    fn user(id: String) -> User {
        User {
            id: 1,
            name: id,
            kind: UserKind::User,
        }
    }

    async fn delayed() -> bool {
        tokio::time::delay_for(std::time::Duration::from_millis(100)).await;
        true
    }
}

struct Mutation;

#[juniper::graphql_object]
impl Mutation {}

#[tokio::test]
async fn async_simple() {
    let schema = RootNode::new(Query, Mutation);
    let doc = r#"
        query {
            fieldSync
            fieldAsyncPlain
            delayed
            user(id: "user1") {
                kind
                name
                delayed
            }
        }
    "#;

    let vars = Default::default();
    let (res, errs) = juniper::execute_async(doc, None, &schema, &vars, &())
        .await
        .unwrap();

    assert!(errs.is_empty());

    let mut obj = res.into_object().unwrap();
    obj.sort_by_field();
    let value = Value::Object(obj);

    assert_eq!(
        value,
        graphql_value!({
            "delayed": true,
            "fieldAsyncPlain": "field_async_plain",
            "fieldSync": "field_sync",
            "user": {
                "delayed": true,
                "kind": "USER",
                "name": "user1",
            },
        }),
    );
}

fn main() {}
<commit_msg>Added a small test for field validation error in the async executor<commit_after>use juniper::{graphql_value, RootNode, Value, GraphQLError};

#[derive(juniper::GraphQLEnum)]
enum UserKind {
    Admin,
    User,
    Guest,
}

struct User {
    id: u64,
    name: String,
    kind: UserKind,
}

#[juniper::graphql_object]
impl User {
    async fn name(&self) -> &str {
        &self.name
    }

    async fn friends(&self) -> Vec<User> {
        (0..10)
            .map(|index| User {
                id: index,
                name: format!("user{}", index),
                kind: UserKind::User,
            })
            .collect()
    }

    async fn kind(&self) -> &UserKind {
        &self.kind
    }

    async fn delayed() -> bool {
        tokio::time::delay_for(std::time::Duration::from_millis(100)).await;
        true
    }
}

struct Query;

#[juniper::graphql_object]
impl Query {
    fn field_sync(&self) -> &'static str {
        "field_sync"
    }

    async fn field_async_plain() -> String {
        "field_async_plain".to_string()
    }

    fn user(id: String) -> User {
        User {
            id: 1,
            name: id,
            kind: UserKind::User,
        }
    }

    async fn delayed() -> bool {
        tokio::time::delay_for(std::time::Duration::from_millis(100)).await;
        true
    }
}

struct Mutation;

#[juniper::graphql_object]
impl Mutation {}

#[tokio::test]
async fn async_simple() {
    let schema = RootNode::new(Query, Mutation);
    let doc = r#"
        query {
            fieldSync
            fieldAsyncPlain
            delayed
            user(id: "user1") {
                kind
                name
                delayed
            }
        }
    "#;

    let vars = Default::default();
    let (res, errs) = juniper::execute_async(doc, None, &schema, &vars, &())
        .await
        .unwrap();

    assert!(errs.is_empty());

    let mut obj = res.into_object().unwrap();
    obj.sort_by_field();
    let value = Value::Object(obj);

    assert_eq!(
        value,
        graphql_value!({
            "delayed": true,
            "fieldAsyncPlain": "field_async_plain",
            "fieldSync": "field_sync",
            "user": {
                "delayed": true,
                "kind": "USER",
                "name": "user1",
            },
        }),
    );
}

#[tokio::test]
async fn async_field_validation_error() {
    let schema = RootNode::new(Query, Mutation);
    let doc = r#"
        query {
            nonExistentField
            fieldSync
            fieldAsyncPlain
            delayed
            user(id: "user1") {
                kind
                name
                delayed
            }
        }
    "#;

    let vars = Default::default();
    let result = juniper::execute_async(doc, None, &schema, &vars, &())
        .await;
    assert!(result.is_err());

    let error = result.err().unwrap();
    let is_validation_error = match error {
        GraphQLError::ValidationError(_) => true,
        _ => false
    };
    assert!(is_validation_error);
}

fn main() {}
<|endoftext|>


<commit_before>
use crate::*;
use crate::wpublisher::bool::*;
use wca::*;
use std::env;
use std::fs;
use std::fmt::Write;
use toml_edit::value;
use cargo_metadata::MetadataCommand;
use wtools::error::Error;

///
/// Publish package.
///

pub fn publish( instruction : &instruction::Instruction ) -> Result<(), Error>
{
  let current_path = env::current_dir().unwrap();

  let mut manifest = manifest_get( instruction.subject.as_str() ).unwrap();
  let data = manifest.manifest_data.as_deref_mut().unwrap();

  let mut package_dir = manifest.manifest_path.clone();
  package_dir.pop();

  let output = process::start_sync( "cargo package", &package_dir ).unwrap();
  process::log_output( &output );

  let name = &data[ "package" ][ "name" ].clone();
  let name = name.as_str().unwrap();
  let version = &data[ "package" ][ "version" ].clone();
  let version = version.as_str().unwrap();
  let local_package_path = local_package_path_get( name, version, &manifest.manifest_path );

  let local_package = fs::read( &local_package_path ).unwrap();
  let remote_package = http::retrieve_bytes( name, version ).unwrap();

  let digest_of_local = digest::hash( &local_package );
  let digest_of_remote = digest::hash( &remote_package );

  if digest_of_local != digest_of_remote
  {
    data[ "package" ][ "version" ] = bump( version ).unwrap();
    let version = &data[ "package" ][ "version" ].clone();
    let version = version.as_str().unwrap();
    manifest.store().unwrap();

    let dry = match instruction.properties_map.get( "dry" )
    {
      Some( x ) => x.to_bool_like(),
      None => BoolLike::False,
    };

    if dry == BoolLike::True
    {
      let mut buf = String::new();
      write!( &mut buf, "git commit --dry-run -am \"{} v{}\"", name, version ).unwrap();
      let output = process::start_sync( &buf, &current_path ).unwrap();
      process::log_output( &output );

      let output = process::start_sync( "git push --dry-run", &current_path ).unwrap();
      process::log_output( &output );

      let output = process::start_sync( "cargo publish --dry-run --allow-dirty", &package_dir ).unwrap();
      process::log_output( &output );
    }
    else
    {
      let mut buf = String::new();
      write!( &mut buf, "git commit -am \"{} v{}\"", name, version ).unwrap();
      let output = process::start_sync( &buf, &current_path ).unwrap();
      process::log_output( &output );

      let output = process::start_sync( "git push", &current_path ).unwrap();
      process::log_output( &output );

      let output = process::start_sync( "cargo publish", &package_dir ).unwrap();
      process::log_output( &output );
    }
  }
  else
  {
    println!( "Package {} is up to date", name );
  }

  Ok( () )
}

fn manifest_get( path : &str ) -> anyhow::Result<manifest::Manifest>
{
  let mut manifest = manifest::Manifest::new();
  manifest.manifest_path_from_str( path )?;
  manifest.load()?;
  Ok( manifest )
}

fn local_package_path_get<'a>( name : &'a str, version : &'a str, manifest_path : &'a std::path::PathBuf ) -> std::path::PathBuf
{
  let mut buf = String::new();
  write!( &mut buf, "package/{0}-{1}.crate", name, version ).unwrap();
  let package_metadata = MetadataCommand::new()
  .manifest_path( manifest_path )
  .exec()
  .unwrap();
  let mut local_package_path = std::path::PathBuf::new();
  local_package_path.push( package_metadata.target_directory );
  local_package_path.push( buf );
  local_package_path
}

fn bump( version : &str ) -> anyhow::Result<toml_edit::Item>
{
  let mut splits : Vec<&str> = version.split( "." ).collect();
  let patch_version = splits[ 2 ].parse::<u32>()? + 1;
  let v = &patch_version.to_string();
  splits[ 2 ] = v;
  Ok( value( splits.join( "." ) ) )
}
<commit_msg>Improve routine `publish`, publish multiple packages using globs, skip local packages, handle situation with no remote version<commit_after>
use crate::*;
use crate::wpublisher::bool::*;
use wca::*;
use std::env;
use std::fs;
use std::fmt::Write;
use std::path::PathBuf;
use toml_edit::value;
use cargo_metadata::MetadataCommand;
use wtools::error::Error;

///
/// Publish package.
///

pub fn publish( instruction : &instruction::Instruction ) -> Result<(), Error>
{
  let current_path = env::current_dir().unwrap();

  let paths = files::find( &current_path, instruction.subject.split( " " ).collect::<Vec<&str>>().as_slice() );
  let mut paths = paths.iter().filter_map( | s | if s.ends_with( "Cargo.toml" ) { Some( s.into() ) } else { None } ).collect::<Vec<PathBuf>>();
  if paths.is_empty() /* && !path.glob_is( &instruction.subject ) qqq : implement `glob_is` */
  {
    paths.push( PathBuf::from( &instruction.subject ) );
  }

  for path in paths
  {
    let mut manifest = manifest_get( path ).unwrap();
    if !manifest.package_is() || manifest.local_is()
    {
      continue;
    }
    let data = manifest.manifest_data.as_deref_mut().unwrap();

    let mut package_dir = manifest.manifest_path.clone();
    package_dir.pop();

    let output = process::start_sync( "cargo package", &package_dir ).unwrap();
    process::log_output( &output );

    let name = &data[ "package" ][ "name" ].clone();
    let name = name.as_str().unwrap();
    let version = &data[ "package" ][ "version" ].clone();
    let version = version.as_str().unwrap();
    let local_package_path = local_package_path_get( name, version, &manifest.manifest_path );

    let local_package = fs::read( &local_package_path ).unwrap();
    let remote_package = http::retrieve_bytes( name, version ).unwrap_or_default();

    let digest_of_local = digest::hash( &local_package );
    let digest_of_remote = digest::hash( &remote_package );

    if digest_of_local != digest_of_remote
    {
      data[ "package" ][ "version" ] = bump( version ).unwrap();
      let version = &data[ "package" ][ "version" ].clone();
      let version = version.as_str().unwrap();
      manifest.store().unwrap();

      let dry = match instruction.properties_map.get( "dry" )
      {
        Some( x ) => x.to_bool_like(),
        None => BoolLike::False,
      };

      if dry == BoolLike::True
      {
        let mut buf = String::new();
        write!( &mut buf, "git commit --dry-run -am \"{} v{}\"", name, version ).unwrap();
        let output = process::start_sync( &buf, &current_path ).unwrap();
        process::log_output( &output );

        let output = process::start_sync( "git push --dry-run", &current_path ).unwrap();
        process::log_output( &output );

        let output = process::start_sync( "cargo publish --dry-run --allow-dirty", &package_dir ).unwrap();
        process::log_output( &output );
      }
      else
      {
        let mut buf = String::new();
        write!( &mut buf, "git commit -am \"{} v{}\"", name, version ).unwrap();
        let output = process::start_sync( &buf, &current_path ).unwrap();
        process::log_output( &output );

        let output = process::start_sync( "git push", &current_path ).unwrap();
        process::log_output( &output );

        let output = process::start_sync( "cargo publish", &package_dir ).unwrap();
        process::log_output( &output );
      }
    }
    else
    {
      println!( "Package {} is up to date", name );
    }
  }

  Ok( () )
}

fn manifest_get( path : impl Into<PathBuf> ) -> anyhow::Result<manifest::Manifest>
{
  let mut manifest = manifest::Manifest::new();
  manifest.manifest_path_from_str( path )?;
  manifest.load()?;
  Ok( manifest )
}

fn local_package_path_get<'a>( name : &'a str, version : &'a str, manifest_path : &'a std::path::PathBuf ) -> std::path::PathBuf
{
  let mut buf = String::new();
  write!( &mut buf, "package/{0}-{1}.crate", name, version ).unwrap();
  let package_metadata = MetadataCommand::new()
  .manifest_path( manifest_path )
  .exec()
  .unwrap();
  let mut local_package_path = std::path::PathBuf::new();
  local_package_path.push( package_metadata.target_directory );
  local_package_path.push( buf );
  local_package_path
}

fn bump( version : &str ) -> anyhow::Result<toml_edit::Item>
{
  let mut splits : Vec<&str> = version.split( "." ).collect();
  let patch_version = splits[ 2 ].parse::<u32>()? + 1;
  let v = &patch_version.to_string();
  splits[ 2 ] = v;
  Ok( value( splits.join( "." ) ) )
}
<|endoftext|>


<commit_before>// #[ allow( unused_imports ) ]
// use test_tools::test_suite;

//

#[ derive( Debug ) ]
struct SmokeModuleTest< 'a >
{
  pub dependency_name : &'a str,
  pub version : &'a str,
  pub local_path : &'a str,
  pub code : &'a str,
  pub test_path : std::path::PathBuf,
  pub test_postfix : &'a str,
}

impl< 'a > SmokeModuleTest< 'a >
{
  fn new( dependency_name : &'a str ) -> SmokeModuleTest< 'a >
  {
    let mut test_path = std::env::temp_dir();
    test_path.push( dependency_name );

    SmokeModuleTest
    {
      dependency_name,
      version : "*",
      local_path : "",
      code : "",
      test_path,
      test_postfix : "_smoke_test",
    }
  }

  fn version( &mut self, version : &'a str ) -> &mut SmokeModuleTest< 'a >
  {
    self.version = version;
    self
  }

  fn local_path( &mut self, local_path : &'a str ) -> &mut SmokeModuleTest< 'a >
  {
    self.local_path = local_path;
    self
  }

  fn test_postfix( &mut self, src : &'a str )
  {
    self.test_postfix = src;
  }

  fn code( &mut self, code : &'a str ) -> &mut SmokeModuleTest< 'a >
  {
    self.code = code;
    self
  }

  fn form( &self ) -> Result< (), &'static str >
  {
    std::fs::create_dir( &self.test_path ).unwrap();

    let mut test_path = self.test_path.clone();

    /* create binary test module */
    let test_name = format!( "{}{}", self.dependency_name, self.test_postfix );
    let output = std::process::Command::new( "cargo" )
    .current_dir( &test_path )
    .args([ "new", "--bin", &test_name ])
    .output()
    .expect( "Failed to execute command" );
    println!( "{}", std::str::from_utf8( &output.stderr ).expect( "Found invalid UTF-8" ) );

    test_path.push( test_name );

    /* setup config */
    let local_path = if self.local_path == "" { "".to_string() } else { format!( ", path = \"{}\"", self.local_path ) };
    let dependencies_section = format!( "{} = {{ version = \"{}\"{} }}", self.dependency_name, self.version, &local_path );
    let config_data = format!
    (
      "[package]\n\
      edition = \"2018\"\n\
      name = \"{}_smoke_test\"\n\
      version = \"0.0.1\"\n\
      \n\
      [dependencies]\n\
      {}",
      &self.dependency_name,
      &dependencies_section
    );
    let mut config_path = test_path.clone();
    config_path.push( "Cargo.toml" );
    std::fs::write( config_path, config_data ).unwrap();

    /* write code */
    test_path.push( "src" );
    test_path.push( "main.rs" );
    let code = format!
    (
      "#[ allow( unused_imports ) ]\n\
      fn main()\n\
      {{\n  \
        use {}::*;\n  \
        {}\n\
      }}",
      self.dependency_name,
      self.code
    );
    std::fs::write( &test_path, code ).unwrap();

    Ok( () )
  }

  fn perform( &self ) -> Result<(), &'static str>
  {
    let mut test_path = self.test_path.clone();
    let test_name = format!( "{}{}", self.dependency_name, self.test_postfix );
    test_path.push( test_name );

    let output = std::process::Command::new( "cargo" )
    .current_dir( test_path )
    .args([ "run", "--release" ])
    .output()
    .unwrap();
    println!( "status : {}", output.status );
    println!( "{}", std::str::from_utf8( &output.stdout ).expect( "Found invalid UTF-8" ) );
    println!( "{}", std::str::from_utf8( &output.stderr ).expect( "Found invalid UTF-8" ) );
    assert!( output.status.success(), "Smoke test failed" );

    Ok( () )
  }

  fn clean( &self, force : bool ) -> Result<(), &'static str>
  {
    let result = std::fs::remove_dir_all( &self.test_path );
    if force
    {
      result.unwrap_or_default();
    }
    else
    {
      let msg = format!( "Cannot remove temporary directory {}. Please, remove it manually", &self.test_path.display() );
      result.expect( &msg );
    }
    Ok( () )
  }

}

//
//   index!
//   {
//
//     new,
//     version,
//     local_path,
//     code,
//     form,
//     perform,
//     clean,
//
//   }
//
//

fn smoke_test_run( test_name : &'static str, local : bool )
{
  let module_name = std::env::var( "CARGO_PKG_NAME" ).unwrap();
  let module_path = std::env::var( "CARGO_MANIFEST_DIR" ).unwrap();

  let mut code_path = std::path::PathBuf::from( module_path.clone() );

  code_path.push( "rust" );
  code_path.push( "test" );
  code_path.push( if module_name.starts_with( "w" ) { &module_name[ 1.. ] } else { module_name.as_str() } );
  code_path.push( "_asset" );
  code_path.push( "smoke.rs" );

  let mut t = SmokeModuleTest::new( module_name.as_str() );
  t.clean( true ).unwrap();
  t.test_postfix( test_name );

  let data;
  if code_path.exists()
  {
    data = std::fs::read_to_string( code_path ).unwrap();
    t.code( &data );
  }

  t.version( "*" );
  if local
  {
    t.local_path( module_path.as_str() );
  }

  t.form().unwrap();
  t.perform().unwrap();
  t.clean( false ).unwrap();

}

//

// #[ test ]
// fn local_smoke_test()
// {
//   if let Ok( value ) = std::env::var( "WITH_SMOKE" )
//   {
//     match value.as_str()
//     {
//       "false" => {},
//       "local" => smoke_test_run( "local_smoke_test", true ),
//       "published" => {},
//       _ =>
//       {
//         smoke_test_run( "local_smoke_test", true );
//       },
//     }
//   }
// }

//

#[ test ]
fn published_smoke_test()
{
  if let Ok( value ) = std::env::var( "WITH_SMOKE" )
  {
    match value.as_str()
    {
      "false" => {},
      "local" => {},
      "published" => smoke_test_run( "published_smoke_test", false ),
      _ =>
      {
        smoke_test_run( "published_smoke_test", false );
      },
    }
  }
}
<commit_msg>Extend smoke test `smoke_test`, add condition to skip testing<commit_after>// #[ allow( unused_imports ) ]
// use test_tools::test_suite;

//

#[ derive( Debug ) ]
struct SmokeModuleTest< 'a >
{
  pub dependency_name : &'a str,
  pub version : &'a str,
  pub local_path : &'a str,
  pub code : &'a str,
  pub test_path : std::path::PathBuf,
  pub test_postfix : &'a str,
}

impl< 'a > SmokeModuleTest< 'a >
{
  fn new( dependency_name : &'a str ) -> SmokeModuleTest< 'a >
  {
    let mut test_path = std::env::temp_dir();
    test_path.push( dependency_name );

    SmokeModuleTest
    {
      dependency_name,
      version : "*",
      local_path : "",
      code : "",
      test_path,
      test_postfix : "_smoke_test",
    }
  }

  fn version( &mut self, version : &'a str ) -> &mut SmokeModuleTest< 'a >
  {
    self.version = version;
    self
  }

  fn local_path( &mut self, local_path : &'a str ) -> &mut SmokeModuleTest< 'a >
  {
    self.local_path = local_path;
    self
  }

  fn test_postfix( &mut self, src : &'a str )
  {
    self.test_postfix = src;
  }

  fn code( &mut self, code : &'a str ) -> &mut SmokeModuleTest< 'a >
  {
    self.code = code;
    self
  }

  fn form( &self ) -> Result< (), &'static str >
  {
    std::fs::create_dir( &self.test_path ).unwrap();

    let mut test_path = self.test_path.clone();

    /* create binary test module */
    let test_name = format!( "{}{}", self.dependency_name, self.test_postfix );
    let output = std::process::Command::new( "cargo" )
    .current_dir( &test_path )
    .args([ "new", "--bin", &test_name ])
    .output()
    .expect( "Failed to execute command" );
    println!( "{}", std::str::from_utf8( &output.stderr ).expect( "Found invalid UTF-8" ) );

    test_path.push( test_name );

    /* setup config */
    let local_path = if self.local_path == "" { "".to_string() } else { format!( ", path = \"{}\"", self.local_path ) };
    let dependencies_section = format!( "{} = {{ version = \"{}\"{} }}", self.dependency_name, self.version, &local_path );
    let config_data = format!
    (
      "[package]\n\
      edition = \"2018\"\n\
      name = \"{}_smoke_test\"\n\
      version = \"0.0.1\"\n\
      \n\
      [dependencies]\n\
      {}",
      &self.dependency_name,
      &dependencies_section
    );
    let mut config_path = test_path.clone();
    config_path.push( "Cargo.toml" );
    std::fs::write( config_path, config_data ).unwrap();

    /* write code */
    test_path.push( "src" );
    test_path.push( "main.rs" );
    let code = format!
    (
      "#[ allow( unused_imports ) ]\n\
      fn main()\n\
      {{\n  \
        use {}::*;\n  \
        {}\n\
      }}",
      self.dependency_name,
      self.code
    );
    std::fs::write( &test_path, code ).unwrap();

    Ok( () )
  }

  fn perform( &self ) -> Result<(), &'static str>
  {
    let mut test_path = self.test_path.clone();
    let test_name = format!( "{}{}", self.dependency_name, self.test_postfix );
    test_path.push( test_name );

    let output = std::process::Command::new( "cargo" )
    .current_dir( test_path )
    .args([ "run", "--release" ])
    .output()
    .unwrap();
    println!( "status : {}", output.status );
    println!( "{}", std::str::from_utf8( &output.stdout ).expect( "Found invalid UTF-8" ) );
    println!( "{}", std::str::from_utf8( &output.stderr ).expect( "Found invalid UTF-8" ) );
    assert!( output.status.success(), "Smoke test failed" );

    Ok( () )
  }

  fn clean( &self, force : bool ) -> Result<(), &'static str>
  {
    let result = std::fs::remove_dir_all( &self.test_path );
    if force
    {
      result.unwrap_or_default();
    }
    else
    {
      let msg = format!( "Cannot remove temporary directory {}. Please, remove it manually", &self.test_path.display() );
      result.expect( &msg );
    }
    Ok( () )
  }

}

//
//   index!
//   {
//
//     new,
//     version,
//     local_path,
//     code,
//     form,
//     perform,
//     clean,
//
//   }
//
//

fn smoke_test_run( test_name : &'static str, local : bool )
{
  let module_name = std::env::var( "CARGO_PKG_NAME" ).unwrap();
  let module_path = std::env::var( "CARGO_MANIFEST_DIR" ).unwrap();

  let mut code_path = std::path::PathBuf::from( module_path.clone() );

  code_path.push( "rust" );
  code_path.push( "test" );
  code_path.push( if module_name.starts_with( "w" ) { &module_name[ 1.. ] } else { module_name.as_str() } );
  code_path.push( "_asset" );
  code_path.push( "smoke.rs" );

  let mut t = SmokeModuleTest::new( module_name.as_str() );
  t.clean( true ).unwrap();
  t.test_postfix( test_name );

  let data;
  if code_path.exists()
  {
    data = std::fs::read_to_string( code_path ).unwrap();
    t.code( &data );
  }

  t.version( "*" );
  if local
  {
    t.local_path( module_path.as_str() );
  }

  t.form().unwrap();
  t.perform().unwrap();
  t.clean( false ).unwrap();

}

//

// #[ test ]
// fn local_smoke_test()
// {
//   if let Ok( value ) = std::env::var( "WITH_SMOKE" )
//   {
//     match value.as_str()
//     {
//       "false" => {},
//       "local" => smoke_test_run( "local_smoke_test", true ),
//       "published" => {},
//       _ =>
//       {
//         smoke_test_run( "local_smoke_test", true );
//       },
//     }
//   }
// }

//

#[ test ]
fn published_smoke_test()
{
  if let Ok( value ) = std::env::var( "WITH_SMOKE" )
  {
    match value.as_str()
    {
      "false" | "0" => {},
      "local" => {},
      "published" => smoke_test_run( "published_smoke_test", false ),
      _ =>
      {
        smoke_test_run( "published_smoke_test", false );
      },
    }
  }
}
<|endoftext|>


<commit_before>//! File tests.
//!
//! This crate contains the main test driver as well as implementations of the
//! available filetest commands.

#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)]
#![warn(unused_import_braces, unstable_features)]
#![cfg_attr(feature="cargo-clippy", allow(
        type_complexity))]
#![cfg_attr(
    feature = "cargo-clippy",
    warn(
        mut_mut, nonminimal_bool, option_map_unwrap_or, option_map_unwrap_or_else, unicode_not_nfc,
        use_self
    )
)]

#[macro_use(dbg)]
extern crate cranelift_codegen;
extern crate cranelift_reader;
extern crate filecheck;
extern crate num_cpus;

use cranelift_reader::TestCommand;
use runner::TestRunner;
use std::path::Path;
use std::time;

mod concurrent;
mod match_directive;
mod runner;
mod runone;
mod subtest;

mod test_binemit;
mod test_cat;
mod test_compile;
mod test_dce;
mod test_domtree;
mod test_legalizer;
mod test_licm;
mod test_postopt;
mod test_preopt;
mod test_print_cfg;
mod test_regalloc;
mod test_shrink;
mod test_simple_gvn;
mod test_verifier;

/// The result of running the test in a file.
type TestResult = Result<time::Duration, String>;

/// Main entry point for `clif-util test`.
///
/// Take a list of filenames which can be either `.clif` files or directories.
///
/// Files are interpreted as test cases and executed immediately.
///
/// Directories are scanned recursively for test cases ending in `.clif`. These test cases are
/// executed on background threads.
///
pub fn run(verbose: bool, files: &[String]) -> TestResult {
    let mut runner = TestRunner::new(verbose);

    for path in files.iter().map(Path::new) {
        if path.is_file() {
            runner.push_test(path);
        } else {
            runner.push_dir(path);
        }
    }

    runner.start_threads();
    runner.run()
}

/// Create a new subcommand trait object to match `parsed.command`.
///
/// This function knows how to create all of the possible `test <foo>` commands that can appear in
/// a `.clif` test file.
fn new_subtest(parsed: &TestCommand) -> subtest::SubtestResult<Box<subtest::SubTest>> {
    match parsed.command {
        "binemit" => test_binemit::subtest(parsed),
        "cat" => test_cat::subtest(parsed),
        "compile" => test_compile::subtest(parsed),
        "dce" => test_dce::subtest(parsed),
        "domtree" => test_domtree::subtest(parsed),
        "legalizer" => test_legalizer::subtest(parsed),
        "licm" => test_licm::subtest(parsed),
        "postopt" => test_postopt::subtest(parsed),
        "preopt" => test_preopt::subtest(parsed),
        "print-cfg" => test_print_cfg::subtest(parsed),
        "regalloc" => test_regalloc::subtest(parsed),
        "shrink" => test_shrink::subtest(parsed),
        "simple-gvn" => test_simple_gvn::subtest(parsed),
        "verifier" => test_verifier::subtest(parsed),
        _ => Err(format!("unknown test command '{}'", parsed.command)),
    }
}
<commit_msg>Fix rustfmt errors.<commit_after>//! File tests.
//!
//! This crate contains the main test driver as well as implementations of the
//! available filetest commands.

#![deny(missing_docs, trivial_numeric_casts, unused_extern_crates)]
#![warn(unused_import_braces, unstable_features)]
#![cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
#![cfg_attr(
    feature = "cargo-clippy",
    warn(
        mut_mut, nonminimal_bool, option_map_unwrap_or, option_map_unwrap_or_else, unicode_not_nfc,
        use_self
    )
)]

#[macro_use(dbg)]
extern crate cranelift_codegen;
extern crate cranelift_reader;
extern crate filecheck;
extern crate num_cpus;

use cranelift_reader::TestCommand;
use runner::TestRunner;
use std::path::Path;
use std::time;

mod concurrent;
mod match_directive;
mod runner;
mod runone;
mod subtest;

mod test_binemit;
mod test_cat;
mod test_compile;
mod test_dce;
mod test_domtree;
mod test_legalizer;
mod test_licm;
mod test_postopt;
mod test_preopt;
mod test_print_cfg;
mod test_regalloc;
mod test_shrink;
mod test_simple_gvn;
mod test_verifier;

/// The result of running the test in a file.
type TestResult = Result<time::Duration, String>;

/// Main entry point for `clif-util test`.
///
/// Take a list of filenames which can be either `.clif` files or directories.
///
/// Files are interpreted as test cases and executed immediately.
///
/// Directories are scanned recursively for test cases ending in `.clif`. These test cases are
/// executed on background threads.
///
pub fn run(verbose: bool, files: &[String]) -> TestResult {
    let mut runner = TestRunner::new(verbose);

    for path in files.iter().map(Path::new) {
        if path.is_file() {
            runner.push_test(path);
        } else {
            runner.push_dir(path);
        }
    }

    runner.start_threads();
    runner.run()
}

/// Create a new subcommand trait object to match `parsed.command`.
///
/// This function knows how to create all of the possible `test <foo>` commands that can appear in
/// a `.clif` test file.
fn new_subtest(parsed: &TestCommand) -> subtest::SubtestResult<Box<subtest::SubTest>> {
    match parsed.command {
        "binemit" => test_binemit::subtest(parsed),
        "cat" => test_cat::subtest(parsed),
        "compile" => test_compile::subtest(parsed),
        "dce" => test_dce::subtest(parsed),
        "domtree" => test_domtree::subtest(parsed),
        "legalizer" => test_legalizer::subtest(parsed),
        "licm" => test_licm::subtest(parsed),
        "postopt" => test_postopt::subtest(parsed),
        "preopt" => test_preopt::subtest(parsed),
        "print-cfg" => test_print_cfg::subtest(parsed),
        "regalloc" => test_regalloc::subtest(parsed),
        "shrink" => test_shrink::subtest(parsed),
        "simple-gvn" => test_simple_gvn::subtest(parsed),
        "verifier" => test_verifier::subtest(parsed),
        _ => Err(format!("unknown test command '{}'", parsed.command)),
    }
}
<|endoftext|>


<commit_before>use std::collections::BitSet;
use std::cell::RefCell;

use value::{Id, Value};
use relation::{Relation, Change, Select};
use view::{View, Table, Union};
use flow::{Node, Flow, Changes};

pub fn schema() -> Vec<(&'static str, Vec<&'static str>, Vec<&'static str>)> {
    // the schema is arranged as (table name, unique key fields, other fields)
    // any field whose type is not described is a UUID

    vec![
    // all state lives in a view of some kind
    // `kind` is one of:
    // "table" - a view which can depend on the past
    // "join" - take the product of multiple views and filter the results
    // "union" - take the union of multiple views
    // "aggregate" - group one view by the contents of another and run reducing functions on the groups
    // "primitive" - a built-in function, represented as a view with one or more non-Data fields
    ("view", vec!["view"], vec!["kind"]),

    // views have fields
    // some fields have constraints on how they can be queried
    // `kind` is one of:
    // "output" - a normal field
    // "scalar input" - a field that must be constrained to a single scalar value
    // "vector input" - a field that must be constrained to a single vector value (in an aggregate)
    ("field", vec!["field"], vec!["view", "kind"]),

    // source ids have two purposes
    // a) uniquely generated ids to disambiguate multiple uses of the same view
    // (eg when joining a view with itself)
    // b) fixed ids to identify views which are used for some specific purpose
    // (these are "insert" and "remove" in tables and "inner" and "outer" in aggregates)
    ("source", vec!["view", "source"], vec!["source view"]),

    // every view also has an implicit "constant" source
    // anywhere source-field is expected, you can instead use "constant"-id
    // `value` may be any valid eve value
    ("constant", vec!["constant"], vec!["value"]),

    // constraints belong to a join view
    // the left and right fields are compared using the operation
    // `operation` is one of "==", "/=", "<", "<=", ">", ">="
    ("constraint", vec!["constraint"], vec!["view"]),
    ("constraint left", vec!["constraint"], vec!["left source", "left field"]),
    ("constraint right", vec!["constraint"], vec!["right source", "right field"]),
    ("constraint operation", vec!["constraint"], vec!["operation"]),

    // aggregates group an "inner" source by the rows of an "outer" source
    // the grouping is determined by binding inner fields to outer fields or constants
    ("aggregate grouping", vec!["aggregate", "inner field"], vec!["group source", "group field"]),
    // before aggregation the groups are sorted
    // `priority` is an f64. higher priority fields are compared first. ties are broken by field id
    // `direction` is one of "ascending" or "descending"
    // fields which have no entry default to 0, "ascending"
    ("aggregate sorting", vec!["aggregate", "inner field"], vec!["priority", "direction"]),
    // groups may optionally be limited by an inner field or constant
    ("aggregate limit from", vec!["aggregate"], vec!["from source", "from field"]),
    ("aggregate limit to", vec!["aggregate"], vec!["to source", "to field"]),
    // the groups may be reduced by binding against reducer sources
    // constants and grouped inner fields may both be used as ScalarInput arguments
    // ungrouped inner fields which are not bound to outer fields may be used as VectorInput arguments
    ("aggregate argument", vec!["aggregate", "reducer source", "reducer field"], vec!["argument source", "argument field"]),

    // views produce output by binding fields from sources
    // each table or join field must be bound exactly once
    // each aggregate field must be bound exactly once and can only bind constants, inner fields or reducer outputs
    // each union field must be bound exactly once per source
    // (the unique key is different for union than for other kinds, so I don't give a key at all)
    ("select", vec![], vec!["view", "view field", "source", "source field"]),

    // things can have human readable names
    // `name` is a string
    ("display name", vec!["id"], vec!["name"]),
    // things can be displayed in ordered lists
    // `priority` is an f64. higher priority things are displayed first. ties are broken by id
    ("display order", vec!["field"], vec!["priority"]),

    // the compiler reflects its decisions into some builtin views
    // a dependency exists whenever the contents on one view depend directly on another
    // `ix` is an integer identifying the edge
    ("dependency", vec!["upstream view", "ix"], vec!["source", "downstream view"]),
    // the schedule determines what order views will be executed in
    // `ix` is an integer. views with lower ixes are executed first.
    ("schedule", vec!["view"], vec!["ix"]),
    ]
}

struct Compiler {
    flow: Flow,
    dependency: Relation,
    schedule: Relation,
}

fn create_dependency(flow: &Flow) -> Relation {
    let mut dependency = Vec::new();
    for view in flow.get_output("view").iter() {
        let mut ix = 0.0;
        for source in flow.get_output("source").find_all("view", &view["view"]) {
            dependency.push(vec![
                source["source view"].clone(),
                Value::Float(ix),
                source["source"].clone(),
                view["view"].clone(),
                ]);
            ix += 1.0;
        }
    }
    Relation{
        fields: vec!["dependency: upstream view".to_owned(), "dependency: ix".to_owned(), "dependency: source".to_owned(), "dependency: downstream view".to_owned()],
        names: vec!["upstream view".to_owned(), "ix".to_owned(), "source".to_owned(), "downstream view".to_owned()],
        index: dependency.into_iter().collect(),
    }
}

fn create_schedule(flow: &Flow) -> Relation {
    // TODO actually schedule sensibly
    // TODO warn about cycles through aggregates
    let mut schedule = Vec::new();
    let mut ix = 0.0;
    for view in flow.get_output("view").iter() {
        schedule.push(vec![Value::Float(ix), view["view"].clone()]);
        ix += 1.0;
    }
    Relation{
        fields: vec!["schedule: ix".to_owned(), "schedule: view".to_owned()],
        names: vec!["ix".to_owned(), "view".to_owned()],
        index: schedule.into_iter().collect(),
    }
}

fn create_single_select(compiler: &Compiler, view_id: &Value, source_id: &Value) -> Select {
    let fields = compiler.flow.get_output("field").find_all("view", view_id).iter().map(|field| {
            compiler.flow.get_output("select").iter().find(|select|
                select["view"] == *view_id
                && select["view field"] == field["field"]
                && select["source"] == *source_id
            ).unwrap()["source field"].as_str().to_owned()
        }).collect();
    Select{fields: fields}
}

fn create_table(compiler: &Compiler, view_id: &Value) -> Table {
    let mut insert = None;
    let mut remove = None;
    for source in compiler.flow.get_output("source").find_all("view", view_id) {
        let select = create_single_select(compiler, view_id, &source["source"]);
        match source["source"].as_str() {
            "insert" => insert = Some(select),
            "remove" => remove = Some(select),
            other => panic!("Unknown table source: {:?}", other),
        }
    }
    Table{insert: insert, remove: remove}
}

fn create_union(compiler: &Compiler, view_id: &Value) -> Union {
    let selects = compiler.dependency.find_all("downstream view", view_id).iter().map(|dependency| {
        create_single_select(compiler, view_id, &dependency["source"])
    }).collect();
    Union{selects: selects}
}

fn create_node(compiler: &Compiler, view_id: &Value, view_kind: &Value) -> Node {
    let view = match view_kind.as_str() {
        "table" => View::Table(create_table(compiler, view_id)),
        "union" => View::Union(create_union(compiler, view_id)),
        other => panic!("Unknown view kind: {}", other),
    };
    let upstream = compiler.dependency.find_all("downstream view", view_id).iter().map(|dependency| {
        compiler.schedule.find_one("view", &dependency["upstream view"])["ix"].as_usize()
    }).collect(); // arrives in ix order so will match the arg order selected by create_join/union
    let mut downstream = compiler.dependency.find_all("upstream view", view_id).iter().map(|dependency| {
        compiler.schedule.find_one("view", &dependency["downstream view"])["ix"].as_usize()
    }).collect::<Vec<_>>();
    downstream.sort();
    downstream.dedup();
    Node{
        id: view_id.as_str().to_owned(),
        view: view,
        upstream: upstream,
        downstream: downstream,
    }
}

fn create_flow(compiler: &Compiler) -> Flow {
    let mut nodes = Vec::new();
    let mut dirty = BitSet::new();
    let mut outputs = Vec::new();
    for schedule in compiler.schedule.iter() {
        let view_table = compiler.flow.get_output("view");
        let view = view_table.find_one("view", &schedule["view"]);
        nodes.push(create_node(compiler, &view["view"], &view["kind"]));
        dirty.insert(schedule["ix"].as_usize());
        let field_table = compiler.flow.get_output("field");
        let fields = field_table.find_all("view", &view["view"]);
        let field_ids = fields.iter().map(|field|
            field["field"].as_str().to_owned()
            ).collect();
        let field_names = fields.iter().map(|field|
            match compiler.flow.get_output("display name").find_maybe("id", &field["field"]) {
                Some(display_name) => display_name["name"].as_str().to_owned(),
                None => "<unnamed>".to_owned(),
            }).collect();
        outputs.push(RefCell::new(Relation::with_fields(field_ids, field_names)));
    }
    Flow{
        nodes: nodes,
        dirty: dirty,
        outputs: outputs,
    }
}

fn reuse_state(compiler: Compiler, flow: &mut Flow, changes: &mut Changes) {
    let Flow{nodes, outputs, ..} = compiler.flow;
    for (node, output) in nodes.into_iter().zip(outputs.into_iter()) {
        let id = &node.id[..];
        if flow.get_ix(id) != None
           && output.borrow().fields == flow.get_output(id).fields {
            flow.set_output(id, output);
        } else {
            changes.push((id.to_owned(), output.borrow().as_remove()));
        }
    }
}

pub fn recompile(old_flow: Flow, changes: &mut Changes) -> Flow {
    let dependency = create_dependency(&old_flow);
    let schedule = create_schedule(&old_flow);
    let compiler = Compiler{
        flow: old_flow,
        dependency: dependency,
        schedule: schedule,
    };
    let mut new_flow = create_flow(&compiler);
    reuse_state(compiler, &mut new_flow, changes);
    new_flow
}

pub fn needs_recompile(changes: &[(Id, Change)]) -> bool {
    let schema = schema();
    changes.iter().any(|&(ref changed_id, _)|
        schema.iter().any(|&(ref compiler_id, _, _)|
            changed_id == compiler_id))
}

pub fn bootstrap(mut flow: Flow) -> Flow {
    let schema = schema();
    for &(ref id, ref unique_fields, ref other_fields) in schema.iter() {
        flow.nodes.push(Node{
            id: format!("{}", id),
                view: View::Union(Union{selects: Vec::new()}), // dummy node
                upstream: Vec::new(),
                downstream: Vec::new(),
            });
        let mut names = unique_fields.iter().chain(other_fields.iter())
            .map(|&field| field.to_owned()).collect::<Vec<_>>();
        names.sort(); // fields are implicitly sorted in the compiler - need to use the same ordering here
        let fields = names.iter().map(|name| format!("{}: {}", id.clone(), name)).collect();
        flow.outputs.push(RefCell::new(Relation::with_fields(fields, names)));
    }
    let mut view_values = Vec::new();
    let mut field_values = Vec::new();
    let mut select_values = Vec::new();
    let mut source_values = Vec::new();
    let mut display_name_values = Vec::new();
    for &(ref id, ref unique_fields, ref other_fields) in schema.iter() {
        view_values.push(vec![string!("{}", id), string!("table")]);
        view_values.push(vec![string!("insert: {}", id), string!("union")]);
        view_values.push(vec![string!("remove: {}", id), string!("union")]);
        for &field in unique_fields.iter().chain(other_fields.iter()) {
            field_values.push(vec![string!("{}: {}", id, field), string!("{}", id), string!("output")]);
            field_values.push(vec![string!("insert: {}: {}", id, field), string!("insert: {}", id), string!("output")]);
            field_values.push(vec![string!("remove: {}: {}", id, field), string!("remove: {}", id), string!("output")]);
            display_name_values.push(vec![string!("{}: {}", id, field), string!("{}", field)]);
            display_name_values.push(vec![string!("insert: {}: {}", id, field), string!("{}", field)]);
            display_name_values.push(vec![string!("remove: {}: {}", id, field), string!("{}", field)]);
            source_values.push(vec![string!("{}", id), string!("insert"), string!("insert: {}", id)]);
            source_values.push(vec![string!("{}", id), string!("remove"), string!("remove: {}", id)]);
            select_values.push(vec![string!("{}", id), string!("{}: {}", id, field), string!("insert"), string!("insert: {}: {}", id, field)]);
            select_values.push(vec![string!("{}", id), string!("{}: {}", id, field), string!("remove"), string!("remove: {}: {}", id, field)]);
        }
    }
    flow.get_output_mut("view").change(&Change{
        fields: vec!["view: view".to_owned(), "view: kind".to_owned()],
        insert: view_values,
        remove: Vec::new(),
    });
    flow.get_output_mut("field").change(&Change{
        fields: vec!["field: field".to_owned(), "field: view".to_owned(), "field: kind".to_owned()],
        insert: field_values,
        remove: Vec::new(),
    });
    flow.get_output_mut("source").change(&Change{
        fields: vec!["source: view".to_owned(), "source: source".to_owned(), "source: source view".to_owned()],
        insert: source_values,
        remove: Vec::new(),
    });
    flow.get_output_mut("select").change(&Change{
        fields: vec!["select: view".to_owned(), "select: view field".to_owned(), "select: source".to_owned(), "select: source field".to_owned()],
        insert: select_values,
        remove: Vec::new(),
    });
    recompile(flow, &mut Vec::new()) // bootstrap away our dummy nodes
}<commit_msg>Fix display order field name<commit_after>use std::collections::BitSet;
use std::cell::RefCell;

use value::{Id, Value};
use relation::{Relation, Change, Select};
use view::{View, Table, Union};
use flow::{Node, Flow, Changes};

pub fn schema() -> Vec<(&'static str, Vec<&'static str>, Vec<&'static str>)> {
    // the schema is arranged as (table name, unique key fields, other fields)
    // any field whose type is not described is a UUID

    vec![
    // all state lives in a view of some kind
    // `kind` is one of:
    // "table" - a view which can depend on the past
    // "join" - take the product of multiple views and filter the results
    // "union" - take the union of multiple views
    // "aggregate" - group one view by the contents of another and run reducing functions on the groups
    // "primitive" - a built-in function, represented as a view with one or more non-Data fields
    ("view", vec!["view"], vec!["kind"]),

    // views have fields
    // some fields have constraints on how they can be queried
    // `kind` is one of:
    // "output" - a normal field
    // "scalar input" - a field that must be constrained to a single scalar value
    // "vector input" - a field that must be constrained to a single vector value (in an aggregate)
    ("field", vec!["field"], vec!["view", "kind"]),

    // source ids have two purposes
    // a) uniquely generated ids to disambiguate multiple uses of the same view
    // (eg when joining a view with itself)
    // b) fixed ids to identify views which are used for some specific purpose
    // (these are "insert" and "remove" in tables and "inner" and "outer" in aggregates)
    ("source", vec!["view", "source"], vec!["source view"]),

    // every view also has an implicit "constant" source
    // anywhere source-field is expected, you can instead use "constant"-id
    // `value` may be any valid eve value
    ("constant", vec!["constant"], vec!["value"]),

    // constraints belong to a join view
    // the left and right fields are compared using the operation
    // `operation` is one of "==", "/=", "<", "<=", ">", ">="
    ("constraint", vec!["constraint"], vec!["view"]),
    ("constraint left", vec!["constraint"], vec!["left source", "left field"]),
    ("constraint right", vec!["constraint"], vec!["right source", "right field"]),
    ("constraint operation", vec!["constraint"], vec!["operation"]),

    // aggregates group an "inner" source by the rows of an "outer" source
    // the grouping is determined by binding inner fields to outer fields or constants
    ("aggregate grouping", vec!["aggregate", "inner field"], vec!["group source", "group field"]),
    // before aggregation the groups are sorted
    // `priority` is an f64. higher priority fields are compared first. ties are broken by field id
    // `direction` is one of "ascending" or "descending"
    // fields which have no entry default to 0, "ascending"
    ("aggregate sorting", vec!["aggregate", "inner field"], vec!["priority", "direction"]),
    // groups may optionally be limited by an inner field or constant
    ("aggregate limit from", vec!["aggregate"], vec!["from source", "from field"]),
    ("aggregate limit to", vec!["aggregate"], vec!["to source", "to field"]),
    // the groups may be reduced by binding against reducer sources
    // constants and grouped inner fields may both be used as ScalarInput arguments
    // ungrouped inner fields which are not bound to outer fields may be used as VectorInput arguments
    ("aggregate argument", vec!["aggregate", "reducer source", "reducer field"], vec!["argument source", "argument field"]),

    // views produce output by binding fields from sources
    // each table or join field must be bound exactly once
    // each aggregate field must be bound exactly once and can only bind constants, inner fields or reducer outputs
    // each union field must be bound exactly once per source
    // (the unique key is different for union than for other kinds, so I don't give a key at all)
    ("select", vec![], vec!["view", "view field", "source", "source field"]),

    // things can have human readable names
    // `name` is a string
    ("display name", vec!["id"], vec!["name"]),
    // things can be displayed in ordered lists
    // `priority` is an f64. higher priority things are displayed first. ties are broken by id
    ("display order", vec!["id"], vec!["priority"]),

    // the compiler reflects its decisions into some builtin views
    // a dependency exists whenever the contents on one view depend directly on another
    // `ix` is an integer identifying the edge
    ("dependency", vec!["upstream view", "ix"], vec!["source", "downstream view"]),
    // the schedule determines what order views will be executed in
    // `ix` is an integer. views with lower ixes are executed first.
    ("schedule", vec!["view"], vec!["ix"]),
    ]
}

struct Compiler {
    flow: Flow,
    dependency: Relation,
    schedule: Relation,
}

fn create_dependency(flow: &Flow) -> Relation {
    let mut dependency = Vec::new();
    for view in flow.get_output("view").iter() {
        let mut ix = 0.0;
        for source in flow.get_output("source").find_all("view", &view["view"]) {
            dependency.push(vec![
                source["source view"].clone(),
                Value::Float(ix),
                source["source"].clone(),
                view["view"].clone(),
                ]);
            ix += 1.0;
        }
    }
    Relation{
        fields: vec!["dependency: upstream view".to_owned(), "dependency: ix".to_owned(), "dependency: source".to_owned(), "dependency: downstream view".to_owned()],
        names: vec!["upstream view".to_owned(), "ix".to_owned(), "source".to_owned(), "downstream view".to_owned()],
        index: dependency.into_iter().collect(),
    }
}

fn create_schedule(flow: &Flow) -> Relation {
    // TODO actually schedule sensibly
    // TODO warn about cycles through aggregates
    let mut schedule = Vec::new();
    let mut ix = 0.0;
    for view in flow.get_output("view").iter() {
        schedule.push(vec![Value::Float(ix), view["view"].clone()]);
        ix += 1.0;
    }
    Relation{
        fields: vec!["schedule: ix".to_owned(), "schedule: view".to_owned()],
        names: vec!["ix".to_owned(), "view".to_owned()],
        index: schedule.into_iter().collect(),
    }
}

fn create_single_select(compiler: &Compiler, view_id: &Value, source_id: &Value) -> Select {
    let fields = compiler.flow.get_output("field").find_all("view", view_id).iter().map(|field| {
            compiler.flow.get_output("select").iter().find(|select|
                select["view"] == *view_id
                && select["view field"] == field["field"]
                && select["source"] == *source_id
            ).unwrap()["source field"].as_str().to_owned()
        }).collect();
    Select{fields: fields}
}

fn create_table(compiler: &Compiler, view_id: &Value) -> Table {
    let mut insert = None;
    let mut remove = None;
    for source in compiler.flow.get_output("source").find_all("view", view_id) {
        let select = create_single_select(compiler, view_id, &source["source"]);
        match source["source"].as_str() {
            "insert" => insert = Some(select),
            "remove" => remove = Some(select),
            other => panic!("Unknown table source: {:?}", other),
        }
    }
    Table{insert: insert, remove: remove}
}

fn create_union(compiler: &Compiler, view_id: &Value) -> Union {
    let selects = compiler.dependency.find_all("downstream view", view_id).iter().map(|dependency| {
        create_single_select(compiler, view_id, &dependency["source"])
    }).collect();
    Union{selects: selects}
}

fn create_node(compiler: &Compiler, view_id: &Value, view_kind: &Value) -> Node {
    let view = match view_kind.as_str() {
        "table" => View::Table(create_table(compiler, view_id)),
        "union" => View::Union(create_union(compiler, view_id)),
        other => panic!("Unknown view kind: {}", other),
    };
    let upstream = compiler.dependency.find_all("downstream view", view_id).iter().map(|dependency| {
        compiler.schedule.find_one("view", &dependency["upstream view"])["ix"].as_usize()
    }).collect(); // arrives in ix order so will match the arg order selected by create_join/union
    let mut downstream = compiler.dependency.find_all("upstream view", view_id).iter().map(|dependency| {
        compiler.schedule.find_one("view", &dependency["downstream view"])["ix"].as_usize()
    }).collect::<Vec<_>>();
    downstream.sort();
    downstream.dedup();
    Node{
        id: view_id.as_str().to_owned(),
        view: view,
        upstream: upstream,
        downstream: downstream,
    }
}

fn create_flow(compiler: &Compiler) -> Flow {
    let mut nodes = Vec::new();
    let mut dirty = BitSet::new();
    let mut outputs = Vec::new();
    for schedule in compiler.schedule.iter() {
        let view_table = compiler.flow.get_output("view");
        let view = view_table.find_one("view", &schedule["view"]);
        nodes.push(create_node(compiler, &view["view"], &view["kind"]));
        dirty.insert(schedule["ix"].as_usize());
        let field_table = compiler.flow.get_output("field");
        let fields = field_table.find_all("view", &view["view"]);
        let field_ids = fields.iter().map(|field|
            field["field"].as_str().to_owned()
            ).collect();
        let field_names = fields.iter().map(|field|
            match compiler.flow.get_output("display name").find_maybe("id", &field["field"]) {
                Some(display_name) => display_name["name"].as_str().to_owned(),
                None => "<unnamed>".to_owned(),
            }).collect();
        outputs.push(RefCell::new(Relation::with_fields(field_ids, field_names)));
    }
    Flow{
        nodes: nodes,
        dirty: dirty,
        outputs: outputs,
    }
}

fn reuse_state(compiler: Compiler, flow: &mut Flow, changes: &mut Changes) {
    let Flow{nodes, outputs, ..} = compiler.flow;
    for (node, output) in nodes.into_iter().zip(outputs.into_iter()) {
        let id = &node.id[..];
        if flow.get_ix(id) != None
           && output.borrow().fields == flow.get_output(id).fields {
            flow.set_output(id, output);
        } else {
            changes.push((id.to_owned(), output.borrow().as_remove()));
        }
    }
}

pub fn recompile(old_flow: Flow, changes: &mut Changes) -> Flow {
    let dependency = create_dependency(&old_flow);
    let schedule = create_schedule(&old_flow);
    let compiler = Compiler{
        flow: old_flow,
        dependency: dependency,
        schedule: schedule,
    };
    let mut new_flow = create_flow(&compiler);
    reuse_state(compiler, &mut new_flow, changes);
    new_flow
}

pub fn needs_recompile(changes: &[(Id, Change)]) -> bool {
    let schema = schema();
    changes.iter().any(|&(ref changed_id, _)|
        schema.iter().any(|&(ref compiler_id, _, _)|
            changed_id == compiler_id))
}

pub fn bootstrap(mut flow: Flow) -> Flow {
    let schema = schema();
    for &(ref id, ref unique_fields, ref other_fields) in schema.iter() {
        flow.nodes.push(Node{
            id: format!("{}", id),
                view: View::Union(Union{selects: Vec::new()}), // dummy node
                upstream: Vec::new(),
                downstream: Vec::new(),
            });
        let mut names = unique_fields.iter().chain(other_fields.iter())
            .map(|&field| field.to_owned()).collect::<Vec<_>>();
        names.sort(); // fields are implicitly sorted in the compiler - need to use the same ordering here
        let fields = names.iter().map(|name| format!("{}: {}", id.clone(), name)).collect();
        flow.outputs.push(RefCell::new(Relation::with_fields(fields, names)));
    }
    let mut view_values = Vec::new();
    let mut field_values = Vec::new();
    let mut select_values = Vec::new();
    let mut source_values = Vec::new();
    let mut display_name_values = Vec::new();
    for &(ref id, ref unique_fields, ref other_fields) in schema.iter() {
        view_values.push(vec![string!("{}", id), string!("table")]);
        view_values.push(vec![string!("insert: {}", id), string!("union")]);
        view_values.push(vec![string!("remove: {}", id), string!("union")]);
        for &field in unique_fields.iter().chain(other_fields.iter()) {
            field_values.push(vec![string!("{}: {}", id, field), string!("{}", id), string!("output")]);
            field_values.push(vec![string!("insert: {}: {}", id, field), string!("insert: {}", id), string!("output")]);
            field_values.push(vec![string!("remove: {}: {}", id, field), string!("remove: {}", id), string!("output")]);
            display_name_values.push(vec![string!("{}: {}", id, field), string!("{}", field)]);
            display_name_values.push(vec![string!("insert: {}: {}", id, field), string!("{}", field)]);
            display_name_values.push(vec![string!("remove: {}: {}", id, field), string!("{}", field)]);
            source_values.push(vec![string!("{}", id), string!("insert"), string!("insert: {}", id)]);
            source_values.push(vec![string!("{}", id), string!("remove"), string!("remove: {}", id)]);
            select_values.push(vec![string!("{}", id), string!("{}: {}", id, field), string!("insert"), string!("insert: {}: {}", id, field)]);
            select_values.push(vec![string!("{}", id), string!("{}: {}", id, field), string!("remove"), string!("remove: {}: {}", id, field)]);
        }
    }
    flow.get_output_mut("view").change(&Change{
        fields: vec!["view: view".to_owned(), "view: kind".to_owned()],
        insert: view_values,
        remove: Vec::new(),
    });
    flow.get_output_mut("field").change(&Change{
        fields: vec!["field: field".to_owned(), "field: view".to_owned(), "field: kind".to_owned()],
        insert: field_values,
        remove: Vec::new(),
    });
    flow.get_output_mut("source").change(&Change{
        fields: vec!["source: view".to_owned(), "source: source".to_owned(), "source: source view".to_owned()],
        insert: source_values,
        remove: Vec::new(),
    });
    flow.get_output_mut("select").change(&Change{
        fields: vec!["select: view".to_owned(), "select: view field".to_owned(), "select: source".to_owned(), "select: source field".to_owned()],
        insert: select_values,
        remove: Vec::new(),
    });
    recompile(flow, &mut Vec::new()) // bootstrap away our dummy nodes
}
<|endoftext|>


<commit_before>#![feature(fs_canonicalize, fundamental)]

extern crate rand;
extern crate hyper;
extern crate regex;
extern crate openssl;
extern crate itertools;
#[cfg(windows)]
extern crate winapi;
#[cfg(windows)]
extern crate winreg;
#[cfg(windows)]
extern crate shell32;
#[cfg(windows)]
extern crate ole32;

pub use errors::*;
pub use install::*;

pub mod env_var;
#[macro_use]
pub mod notify;
pub mod utils;
pub mod temp;

#[cfg(windows)]
pub mod msi;

pub mod dist;
mod errors;
mod install;
<commit_msg>removed stablized fs_cannicalize feature<commit_after>#![feature(fundamental)]

extern crate rand;
extern crate hyper;
extern crate regex;
extern crate openssl;
extern crate itertools;
#[cfg(windows)]
extern crate winapi;
#[cfg(windows)]
extern crate winreg;
#[cfg(windows)]
extern crate shell32;
#[cfg(windows)]
extern crate ole32;

pub use errors::*;
pub use install::*;

pub mod env_var;
#[macro_use]
pub mod notify;
pub mod utils;
pub mod temp;

#[cfg(windows)]
pub mod msi;

pub mod dist;
mod errors;
mod install;
<|endoftext|>


<commit_before>extern mod std;

enum HashEngine { SHA1, SHA128, SHA224, SHA256, SHA384, SHA512, MD5 }

extern mod crypto {
  fn SHA1(src: *u8, sz: libc::c_uint, out: *u8) -> *u8;
  fn MD5(src: *u8, sz: libc::c_uint, out: *u8) -> *u8;
}

extern mod cryptobindings {
  fn wrap_HMAC(method: HashEngine,
    key: *u8,
    key_size: libc::size_t,
    data: *u8,
    size: libc::size_t,
    target: *u8) -> libc::c_uint;
}

struct Digest { digest: ~[u8] }

impl Digest {
    fn new(digest: ~[u8]) -> ~Digest { return ~Digest{ digest: digest } }

    fn hexdigest(&self) -> ~str {
        let mut acc = ~"";
        for self.digest.each |&byte| { acc += fmt!("%02x", byte as uint); }
        acc
    }
}

fn hash(data: ~[u8], hash_func: &fn(*u8, libc::c_uint, *u8) -> *u8, len: uint) -> ~Digest {
  unsafe {
    Digest::new(
      vec::from_buf(
        hash_func(
          vec::raw::to_ptr(data),
          data.len() as libc::c_uint, ptr::null()
        ),
        len
      )
    )
  }
}

fn sha1(data: ~[u8]) -> ~Digest {
  unsafe {
    hash(data, crypto::SHA1, 20)
  }
}

fn md5(data: ~[u8]) -> ~Digest {
  unsafe {
    hash(data, crypto::MD5, 16)
  }
}

fn xor_with(subject: &str, val: u8) -> ~[u8] {
  do subject.to_bytes().map |&c| { val ^ c }
}

fn hmac_sha1(key: ~str, message: ~str) -> ~Digest {
  hmac(key, message, 64, sha1)
}

fn hmac_md5(key: ~str, message: ~str) -> ~Digest {
  hmac(key, message, 64, md5)
}

fn hmac(key: ~str, message: ~str, block_size: uint, hash_func: &fn(~[u8]) -> ~Digest) -> ~Digest {

  let computed_key: &str = if key.len() > block_size {
    hash_func(key.to_bytes()).hexdigest() // TODO this should be .digest more likely
  } else if key.len() < block_size {
    key + str::from_bytes(vec::from_elem(block_size - key.len(), 0))
  } else {
    key
  };

  let o_key_pad = xor_with(computed_key, 0x5c);
  let i_key_pad = xor_with(computed_key, 0x36);
  let bin_message = message.to_bytes();

  hash_func(o_key_pad + hash_func(i_key_pad + bin_message).digest)
}

fn main() {
  if core::os::args().len() < 2 { fail!(~"Nothing to hash: supply an argument") }
  io::println(sha1(core::os::args()[1].clone().to_bytes()).hexdigest());
}

#[test]
fn test_sha1() {
  assert_eq!(sha1("testing SHA1".to_bytes()).hexdigest(), ~"a07bb2f7f56b7b47e54fd9e29b4629c8967dde4c");
}

#[test]
fn test_md5() {
  assert_eq!(md5("testing MD5".to_bytes()).hexdigest(), ~"da35df95d34f166890fa759f5e00e94c");
}

#[test]
fn test_hmac_sha1() {
  assert_eq!(
    hmac_sha1(~"my key", ~"some data to hmac").hexdigest(),
    ~"331c9bf4d7dc8ad7e9bab2f566c8612042a9f4e2"
  )
}

/*
#[test]
fn test_hmac_sha256() {
  assert_eq!(
    hmac(SHA256, ~"my key", ~"some data to hmac"),
    ~"17764a8a2e8c23ae3b9e1781c5ebeb5754c7920806021032e9133051e10118be"
  );
}

#[test]
fn test_hmac_sha512() {
  assert_eq!(
    hmac(SHA512, ~"my key", ~"some data to hmac"),
    ~"b54973feba2e436c4f0911855c80e7320d72edd37b359d6474d714718c52775f163832b79214e9fa9d400208d21372a465b2cda2a1d5ab488bbc02b0daea9626"
  );
}

*/
#[test]
fn test_hmac_md5() {
  assert_eq!(hmac_md5(~"my key", ~"some data to hmac").hexdigest(), ~"befd13e00ee07549520ade402c664a3a");
}
<commit_msg>Remove unused link to C library, associated enum.<commit_after>extern mod std;

extern mod crypto {
  fn SHA1(src: *u8, sz: libc::c_uint, out: *u8) -> *u8;
  fn MD5(src: *u8, sz: libc::c_uint, out: *u8) -> *u8;
}

struct Digest { digest: ~[u8] }

impl Digest {
    fn new(digest: ~[u8]) -> ~Digest { return ~Digest{ digest: digest } }

    fn hexdigest(&self) -> ~str {
        let mut acc = ~"";
        for self.digest.each |&byte| { acc += fmt!("%02x", byte as uint); }
        acc
    }
}

fn hash(data: ~[u8], hash_func: &fn(*u8, libc::c_uint, *u8) -> *u8, len: uint) -> ~Digest {
  unsafe {
    Digest::new(
      vec::from_buf(
        hash_func(
          vec::raw::to_ptr(data),
          data.len() as libc::c_uint, ptr::null()
        ),
        len
      )
    )
  }
}

fn sha1(data: ~[u8]) -> ~Digest {
  unsafe {
    hash(data, crypto::SHA1, 20)
  }
}

fn md5(data: ~[u8]) -> ~Digest {
  unsafe {
    hash(data, crypto::MD5, 16)
  }
}

fn xor_with(subject: &str, val: u8) -> ~[u8] {
  do subject.to_bytes().map |&c| { val ^ c }
}

fn hmac_sha1(key: ~str, message: ~str) -> ~Digest {
  hmac(key, message, 64, sha1)
}

fn hmac_md5(key: ~str, message: ~str) -> ~Digest {
  hmac(key, message, 64, md5)
}

fn hmac(key: ~str, message: ~str, block_size: uint, hash_func: &fn(~[u8]) -> ~Digest) -> ~Digest {

  let computed_key: &str = if key.len() > block_size {
    hash_func(key.to_bytes()).hexdigest() // TODO this should be .digest more likely
  } else if key.len() < block_size {
    key + str::from_bytes(vec::from_elem(block_size - key.len(), 0))
  } else {
    key
  };

  let o_key_pad = xor_with(computed_key, 0x5c);
  let i_key_pad = xor_with(computed_key, 0x36);
  let bin_message = message.to_bytes();

  hash_func(o_key_pad + hash_func(i_key_pad + bin_message).digest)
}

fn main() {
  if core::os::args().len() < 2 { fail!(~"Nothing to hash: supply an argument") }
  io::println(sha1(core::os::args()[1].clone().to_bytes()).hexdigest());
}

#[test]
fn test_sha1() {
  assert_eq!(sha1("testing SHA1".to_bytes()).hexdigest(), ~"a07bb2f7f56b7b47e54fd9e29b4629c8967dde4c");
}

#[test]
fn test_md5() {
  assert_eq!(md5("testing MD5".to_bytes()).hexdigest(), ~"da35df95d34f166890fa759f5e00e94c");
}

#[test]
fn test_hmac_sha1() {
  assert_eq!(
    hmac_sha1(~"my key", ~"some data to hmac").hexdigest(),
    ~"331c9bf4d7dc8ad7e9bab2f566c8612042a9f4e2"
  )
}

/*
#[test]
fn test_hmac_sha256() {
  assert_eq!(
    hmac(SHA256, ~"my key", ~"some data to hmac"),
    ~"17764a8a2e8c23ae3b9e1781c5ebeb5754c7920806021032e9133051e10118be"
  );
}

#[test]
fn test_hmac_sha512() {
  assert_eq!(
    hmac(SHA512, ~"my key", ~"some data to hmac"),
    ~"b54973feba2e436c4f0911855c80e7320d72edd37b359d6474d714718c52775f163832b79214e9fa9d400208d21372a465b2cda2a1d5ab488bbc02b0daea9626"
  );
}

*/
#[test]
fn test_hmac_md5() {
  assert_eq!(hmac_md5(~"my key", ~"some data to hmac").hexdigest(), ~"befd13e00ee07549520ade402c664a3a");
}
<|endoftext|>


<commit_before>// library
extern crate my_extern_lib;

// modules
mod simple_functions {
    pub fn print_hello_world() {
        println!("Hello, World! (from the simple_functions module)");
     }

    // nested modules
    pub mod simple_math {
        pub fn multiple_two_integers(a: i32, b: i32) -> i32 {
            a * b
        }
    }
}

use simple_functions::simple_math::multiple_two_integers;

fn print_some_msg() {
    println!("Modules: printing from the outer function");
}

mod sample_module {

    pub fn call_sample_module() {
        use second_module::print_some_msg as print_second;
        use self::second_module::print_some_msg as print_second_sample;
        use super::print_some_msg as print_outside;
        print_outside();
        print_second();
        print_some_msg();
        print_second_sample();
    }

    mod second_module {

        pub fn print_some_msg() {
            println!("Modules: printing from the second module inside the sample module");
        }

    }

    fn print_some_msg() {
        println!("Modules: printing from the inside of the sample module");
    }

}

mod second_module {
    pub fn print_some_msg() {
        println!("Modules: printing from the second module");
    }
}

mod modules;

fn main() {

    // formatted output
    println!("Hello, Rust!");
    println!("Integer number = {}", 23);
    println!("Float number = {}", 1.012);
    println!("Repeat printing: {0}, {1}, {1}, {3}, {2}", 2, 1, 44, 9);
    println!("Named arguments: {name}, {age}, {occupation}", age="24", name="Ann", occupation="Designer");
    println!("{:08b} XOR {:08b} = {:08b}", 3i8, 32i8, 3i8 ^ 34i8);
    println!("Floating point number {:?}", 2.910210);
    println!("Hex: {:08X}, {:08x}", 131342112, 131342112);
    // TODO find out why this doesn't work:
    //println!("{0:08X}, {0:08x}", 7661);

    // variables
    let integer = 3i32;
    let floating_point = 2.1137;

    let mut u_integer = 3u32;
    //integer += 1; error: an immutable variable
    u_integer += 1;

    println!("{}, {}, {}", integer, floating_point, u_integer);
    // TODO find out why snake case instead of camel case

    // shadowing
    let first_var = 4;
    {
        let first_var = 51;
        println!("first_var = {}", first_var);
    }
    println!("first_var = {}", first_var);

    // unitialized variables
    let uninit_var;
    //println!("uninit_var = {}", uninit_var); error: use of an init variable
    uninit_var = 231.2;
    println!("already initialized uninit_var = {}", uninit_var);

    // type casting
    let a_integer = 0x40_u8;
    let a_char = a_integer as char;
    println!("char cast from integer {}: {}", a_integer, a_char);

    let a_float = 8.45511;
    println!("integer cast from float {}: {}", a_float, a_float as i32);

    println!("Binary represntation of {}: {:08b}", -1_i8, -1_i8);
    println!("Binary represntation of {}: {:08b}", -2_i8, -2_i8);

    // aliases
    type FloatingPoint32 = f32;
    let a_float_2 : FloatingPoint32 = 3 as f32;
    println!("Type alias: {}, size of var {}", a_float_2, std::mem::size_of_val(&a_float_2));

    // expressions
    let expr = {
        let x = 4.09;
        let y = 1.28;
        println!("x = {}, y = {}", x, y);
        x / y
    };
    println!("expr = {}", expr);

    // if-statement (every if-statement is an expression too, which is really a cool thing)
    let speed = 10;
    let mass = 890;
    let consumption =
        if speed < 0 {
            -1.0
        }
        else if speed == 0 {
            0.8
        }
        else if speed > 0 && speed < 10 {
            18.52
        }
        else if speed >= 10 && speed < 30 {
            let x = mass / speed;
            (x as f32) * 0.05
        }
        else {
            11.71
        };
        println!("Speed = {}, consumption = {}", speed, consumption);

        // loop
        let mut count = 0u32;
        loop {
            println!("loop iteration #{}", count);
            count += 1;
            if count > 9 {
            break;
            }
        }

        count = 0;
        while count < 10 {
            println!("while loop iteration #{}", count);
            count += 1;
        }

        for n in 0u32..10 {
            println!("for loop iteration #{}", n);
        }

        // matching
        let age = 19;
        match age {
            1  => println!("Seems like 1"),
            5  => println!("It's 5"),
            18 => println!("Exactly 18!"),
            _  => println!("I couldn't guess :("),
        }

        match age {
            a if a > 1 && a <= 9  => println!("The age is in range [1,9]"),
            a if a > 9 && a <= 19 => println!("The age is in range [10, 19]"),
            _                     => println!("Nothing, I don't know what range the age is in :("),
        }

        // the previous match is equivalent to the following:
        match age {
            a @ 1...9   => println!("The age is {} and in range [1,9]", a),
            a @ 10...19 => println!("The age is {} and in range [10, 19]", a),
            a           => println!("Nothing, I don't know what range the age {} is in :(", a),
        }

        // if let
        let a_some = Some(0.0008);
        if let Some(i) = a_some {
            println!("a_some is not None, {}", i);
            println!("result {}",  9.0 / i);
        }
        else {
            println!("None");
        }

        // while let
        let mut a_optional = Some(10);

        while let Some(i) = a_optional {
            if i == 20 {
                println!("while let: i equals 20, leave");
                a_optional = None;
            }
            else {
                a_optional = Some(i + 1);
            }
        }

        // functions, finally!
        let first_integer: i32 = -20;
        let second_integer: i32 = 8;
        let result_of_addition = add_two_integers(first_integer, second_integer);
        println!("{} + {} = {}", first_integer, second_integer, result_of_addition);

        simple_functions::print_hello_world();
        let mul_result = simple_functions::simple_math::multiple_two_integers(3, 15);
        println!("Modules: multiplication result = {}", mul_result);

        // this doesn't work.. why?
        println!("Modules: multiplication result 2 = {}", multiple_two_integers(-1, 8));

        // "super" and "self"
        sample_module::call_sample_module();

        // file hierarchy
        {
            let a : i32 = 4;
            let b : i32 = 15;
            println!("modules::math {} + {} = {}", a, b, modules::math::add_two_int(a, b));
        }

        // call external library
        my_extern_lib::run(5);

        // tuples
        let pair = ("key", 4);
        println!("tuple value: ({}, {})", pair.0, pair.1);
        println!("tuple value: {:?}", pair);

        // structs
        let bmw: Car = Car {color: "Blue".to_string(), weight: 940};
        println!("BMW: {} - {}", bmw.color, bmw.weight);

        // tuple structs
        let color_1: RgbColor = RgbColor(123, 33, 81);
        println!("RGB color: {}, {}, {}", color_1.0, color_1.1, color_1.2);

        // unit structs
        let _nil = Nil;

        // a struct with a constructor and getter
        let rabbit = my_extern_lib::Animal::new(2, 4, "The King");
        println!("Rabbit: {}, {}, {}", rabbit.age, rabbit.weight, rabbit.get_secret_info());

        // generics
        {
            struct ThreeValues<T, U, V> {
                first: T,
                second: U,
                third: V,
            }

            let three_values = ThreeValues { first: 4, second: 2.01, third: "hello" };
            println!("Generic data structure: {}, {}, {}", three_values.first, three_values.second, three_values.third);

            // generic function
            fn swap<U, V>(first_value: U, second_value: V) -> (V, U) {
                (second_value, first_value)
            }

            let random_tuple = swap(4, 2);
            println!("Use unused variables: {} {}", random_tuple.0, random_tuple.1);

        }
}

// a C-like struct
struct Car {
    color: String,
    weight: u32,
}

// a tuple struct s
struct RgbColor(i8, i8, i8);

// a unit struct
struct Nil;

fn add_two_integers(a: i32, b: i32) -> i32 {
    a + b
}
<commit_msg>Progress: heap allocation(box)<commit_after>// library
extern crate my_extern_lib;

// modules
mod simple_functions {
    pub fn print_hello_world() {
        println!("Hello, World! (from the simple_functions module)");
     }

    // nested modules
    pub mod simple_math {
        pub fn multiple_two_integers(a: i32, b: i32) -> i32 {
            a * b
        }
    }
}

use simple_functions::simple_math::multiple_two_integers;

fn print_some_msg() {
    println!("Modules: printing from the outer function");
}

mod sample_module {

    pub fn call_sample_module() {
        use second_module::print_some_msg as print_second;
        use self::second_module::print_some_msg as print_second_sample;
        use super::print_some_msg as print_outside;
        print_outside();
        print_second();
        print_some_msg();
        print_second_sample();
    }

    mod second_module {

        pub fn print_some_msg() {
            println!("Modules: printing from the second module inside the sample module");
        }

    }

    fn print_some_msg() {
        println!("Modules: printing from the inside of the sample module");
    }

}

mod second_module {
    pub fn print_some_msg() {
        println!("Modules: printing from the second module");
    }
}

mod modules;

fn main() {

    // formatted output
    println!("Hello, Rust!");
    println!("Integer number = {}", 23);
    println!("Float number = {}", 1.012);
    println!("Repeat printing: {0}, {1}, {1}, {3}, {2}", 2, 1, 44, 9);
    println!("Named arguments: {name}, {age}, {occupation}", age="24", name="Ann", occupation="Designer");
    println!("{:08b} XOR {:08b} = {:08b}", 3i8, 32i8, 3i8 ^ 34i8);
    println!("Floating point number {:?}", 2.910210);
    println!("Hex: {:08X}, {:08x}", 131342112, 131342112);
    // TODO find out why this doesn't work:
    //println!("{0:08X}, {0:08x}", 7661);

    // variables
    let integer = 3i32;
    let floating_point = 2.1137;

    let mut u_integer = 3u32;
    //integer += 1; error: an immutable variable
    u_integer += 1;

    println!("{}, {}, {}", integer, floating_point, u_integer);
    // TODO find out why snake case instead of camel case

    // shadowing
    let first_var = 4;
    {
        let first_var = 51;
        println!("first_var = {}", first_var);
    }
    println!("first_var = {}", first_var);

    // unitialized variables
    let uninit_var;
    //println!("uninit_var = {}", uninit_var); error: use of an init variable
    uninit_var = 231.2;
    println!("already initialized uninit_var = {}", uninit_var);

    // type casting
    let a_integer = 0x40_u8;
    let a_char = a_integer as char;
    println!("char cast from integer {}: {}", a_integer, a_char);

    let a_float = 8.45511;
    println!("integer cast from float {}: {}", a_float, a_float as i32);

    println!("Binary represntation of {}: {:08b}", -1_i8, -1_i8);
    println!("Binary represntation of {}: {:08b}", -2_i8, -2_i8);

    // aliases
    type FloatingPoint32 = f32;
    let a_float_2 : FloatingPoint32 = 3 as f32;
    println!("Type alias: {}, size of var {}", a_float_2, std::mem::size_of_val(&a_float_2));

    // expressions
    let expr = {
        let x = 4.09;
        let y = 1.28;
        println!("x = {}, y = {}", x, y);
        x / y
    };
    println!("expr = {}", expr);

    // if-statement (every if-statement is an expression too, which is really a cool thing)
    let speed = 10;
    let mass = 890;
    let consumption =
        if speed < 0 {
            -1.0
        }
        else if speed == 0 {
            0.8
        }
        else if speed > 0 && speed < 10 {
            18.52
        }
        else if speed >= 10 && speed < 30 {
            let x = mass / speed;
            (x as f32) * 0.05
        }
        else {
            11.71
        };
        println!("Speed = {}, consumption = {}", speed, consumption);

        // loop
        let mut count = 0u32;
        loop {
            println!("loop iteration #{}", count);
            count += 1;
            if count > 9 {
            break;
            }
        }

        count = 0;
        while count < 10 {
            println!("while loop iteration #{}", count);
            count += 1;
        }

        for n in 0u32..10 {
            println!("for loop iteration #{}", n);
        }

        // matching
        let age = 19;
        match age {
            1  => println!("Seems like 1"),
            5  => println!("It's 5"),
            18 => println!("Exactly 18!"),
            _  => println!("I couldn't guess :("),
        }

        match age {
            a if a > 1 && a <= 9  => println!("The age is in range [1,9]"),
            a if a > 9 && a <= 19 => println!("The age is in range [10, 19]"),
            _                     => println!("Nothing, I don't know what range the age is in :("),
        }

        // the previous match is equivalent to the following:
        match age {
            a @ 1...9   => println!("The age is {} and in range [1,9]", a),
            a @ 10...19 => println!("The age is {} and in range [10, 19]", a),
            a           => println!("Nothing, I don't know what range the age {} is in :(", a),
        }

        // if let
        let a_some = Some(0.0008);
        if let Some(i) = a_some {
            println!("a_some is not None, {}", i);
            println!("result {}",  9.0 / i);
        }
        else {
            println!("None");
        }

        // while let
        let mut a_optional = Some(10);

        while let Some(i) = a_optional {
            if i == 20 {
                println!("while let: i equals 20, leave");
                a_optional = None;
            }
            else {
                a_optional = Some(i + 1);
            }
        }

        // functions, finally!
        let first_integer: i32 = -20;
        let second_integer: i32 = 8;
        let result_of_addition = add_two_integers(first_integer, second_integer);
        println!("{} + {} = {}", first_integer, second_integer, result_of_addition);

        simple_functions::print_hello_world();
        let mul_result = simple_functions::simple_math::multiple_two_integers(3, 15);
        println!("Modules: multiplication result = {}", mul_result);

        // this doesn't work.. why?
        println!("Modules: multiplication result 2 = {}", multiple_two_integers(-1, 8));

        // "super" and "self"
        sample_module::call_sample_module();

        // file hierarchy
        {
            let a : i32 = 4;
            let b : i32 = 15;
            println!("modules::math {} + {} = {}", a, b, modules::math::add_two_int(a, b));
        }

        // call external library
        my_extern_lib::run(5);

        // tuples
        let pair = ("key", 4);
        println!("tuple value: ({}, {})", pair.0, pair.1);
        println!("tuple value: {:?}", pair);

        // structs
        let bmw: Car = Car {color: "Blue".to_string(), weight: 940};
        println!("BMW: {} - {}", bmw.color, bmw.weight);

        // tuple structs
        let color_1: RgbColor = RgbColor(123, 33, 81);
        println!("RGB color: {}, {}, {}", color_1.0, color_1.1, color_1.2);

        // unit structs
        let _nil = Nil;

        // a struct with a constructor and getter
        let rabbit = my_extern_lib::Animal::new(2, 4, "The King");
        println!("Rabbit: {}, {}, {}", rabbit.age, rabbit.weight, rabbit.get_secret_info());

        // generics
        {
            struct ThreeValues<T, U, V> {
                first: T,
                second: U,
                third: V,
            }

            let three_values = ThreeValues { first: 4, second: 2.01, third: "hello" };
            println!("Generic data structure: {}, {}, {}", three_values.first, three_values.second, three_values.third);

            // generic function
            fn swap<U, V>(first_value: U, second_value: V) -> (V, U) {
                (second_value, first_value)
            }

            let random_tuple = swap(4, 2);
            println!("Use unused variables: {} {}", random_tuple.0, random_tuple.1);

        }

        // box (heap allocation)
        {

            let toyota: Car = Car {color: "Green".to_string(), weight: 1040,};
            let porche: Box<Car> = Box::new(Car {color: "Black".to_string(), weight: 876, });

            println!("Toyota's size on stack is {}", std::mem::size_of_val(&toyota));
            println!("Boxed porche's size on stack is {}", std::mem::size_of_val(&porche));

            let unboxed_porche: Car = *porche;
            println!("Unboxed porche's size on stack is {}", std::mem::size_of_val(&unboxed_porche));

        }

}

// a C-like struct
struct Car {
    color: String,
    weight: u32,
}

// a tuple struct s
struct RgbColor(i8, i8, i8);

// a unit struct
struct Nil;

fn add_two_integers(a: i32, b: i32) -> i32 {
    a + b
}
<|endoftext|>


<commit_before>#![feature(no_std)]
#![feature(core)]
#![feature(lang_items)]
#![no_std]

#![crate_type="staticlib"]

extern crate core;
mod sysctl;
mod runtime;

#[no_mangle] pub fn main()
{
    let clock_config = sysctl::SYSCTL_SYSDIV_2_5 + sysctl::SYSCTL_USE_PLL +
                       sysctl::SYSCTL_XTAL_16MHZ + sysctl::SYSCTL_OSC_MAIN;
    sysctl::clock_set(clock_config);

}
<commit_msg>Implement blinking LED demo<commit_after>#![feature(no_std)]
#![feature(core)]
#![feature(lang_items)]
#![no_std]

#![crate_type="staticlib"]

extern crate core;

mod runtime;
mod sysctl;
mod led_driver;
mod gpio;

fn clock_init() -> () {
    let clock_config = sysctl::SYSCTL_SYSDIV_2_5 + sysctl::SYSCTL_USE_PLL +
                       sysctl::SYSCTL_XTAL_16MHZ + sysctl::SYSCTL_OSC_MAIN;
    sysctl::clock_set(clock_config);
}

#[no_mangle] pub fn main()
{
    clock_init();
    led_driver::led_init();

    loop {
        let mut i = 0;
        while i < 1000000 {
            i += 1;
            led_driver::set_red(false);
        }

        i = 0;

        while i < 1000000 {
            i += 1;
            led_driver::set_red(true);
        }
    }
}

<|endoftext|>


<commit_before>//
// Tests for single-use-variable elimination
//

// Check forward movement of values
#[test="simple_fwd_exp"]
fn simple_fwd(a: i32) -> (i32,)
{
	let v: i32;
	bb0: {
		ASSIGN v = a;
		ASSIGN retval = (v,);
	} RETURN;
}
fn simple_fwd_exp(a: i32) -> (i32,)
{
	bb0: {
		ASSIGN retval = (a,);
	} RETURN;
}

// Reverse (upwards) movement
#[test="simple_rev_exp"]
fn simple_rev(a: i32) -> (i32,)
{
	let v: (i32,);
	bb0: {
		ASSIGN v = (a,);
		ASSIGN retval = v;
	} RETURN;
}
fn simple_rev_exp(a: i32) -> (i32,)
{
	bb0: {
		ASSIGN retval = (a,);
	} RETURN;
}

// Check that if there's a mutable borrow of the source, that the source isn't propagated forwards
// - NOTE: This relies on the optimiser not being smart enough to move the `retval` construction up
#[test="nomut"]
fn nomut(a: i32) -> (i32,)
{
	let v: i32;
	let ba: &mut i32;
	bb0: {
		ASSIGN v = a;
		ASSIGN ba = &mut a;
		//ASSIGN a* = +0;
		ASSIGN retval = (v,);
		DROP ba;
	} RETURN;
}
<commit_msg>mir_opt_test - Add comment to one of the tests about the reasoning<commit_after>//
// Tests for single-use-variable elimination
//

// Check forward movement of values
#[test="simple_fwd_exp"]
fn simple_fwd(a: i32) -> (i32,)
{
	let v: i32;
	bb0: {
		ASSIGN v = a;
		ASSIGN retval = (v,);
	} RETURN;
}
fn simple_fwd_exp(a: i32) -> (i32,)
{
	bb0: {
		ASSIGN retval = (a,);
	} RETURN;
}

// Reverse (upwards) movement
#[test="simple_rev_exp"]
fn simple_rev(a: i32) -> (i32,)
{
	let v: (i32,);
	bb0: {
		ASSIGN v = (a,);
		ASSIGN retval = v;
	} RETURN;
}
fn simple_rev_exp(a: i32) -> (i32,)
{
	bb0: {
		ASSIGN retval = (a,);
	} RETURN;
}

// Check that if there's a mutable borrow of the source, that the source isn't propagated forwards
// - NOTE: This relies on the optimiser not being smart enough to move the `retval` construction up
#[test="nomut"]
fn nomut(a: i32) -> (i32,)
{
	let v: i32;
	let ba: &mut i32;
	bb0: {
		ASSIGN v = a;
		ASSIGN ba = &mut a;
		//ASSIGN ba* = +0;	// This could be here, which is why the optimisation is unsound
		ASSIGN retval = (v,);
		DROP ba;
	} RETURN;
}
<|endoftext|>


<commit_before>// Copyright 2015 Ilkka Rauta
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate linuxdvb;

use std::fs;
use std::error::Error;
use std::path::Path;

use linuxdvb::{Frontend,ReadWriteMode,BlockMode};
use linuxdvb::properties::GetProperty as GP;
use linuxdvb::properties::GetPropertyValue as GPV;

type SimpleResult<T> = Result<T, Box<Error>>;

fn show_frontend_info(path: &Path, yet_another_one: bool) -> SimpleResult<()> {
    let frontend = Frontend::open(path, ReadWriteMode::ReadOnly, BlockMode::NonBlocking).unwrap();
    if yet_another_one {
        println!("--");
    }
    println!("Device: {}", path.to_string_lossy());
    let info = try!(frontend.get_info());
    println!("Name: {}", info.name);

    let properties = try!(frontend.get_properties(&[
        GP::DtvEnumDelsys
        ]));
    if let GPV::DtvEnumDelsys(delsys) = properties[0] {
        println!("Supported delivery systems: {:?}", delsys.delivery_systems());
    }

    println!("Minimal frequency: {}", info.frequency_min);
    println!("Maximal frequency: {}", info.frequency_max);
    println!("Frequency step: {}", info.frequency_stepsize);
    println!("Frequency tolerance: {}", info.frequency_tolerance);
    println!("Minimal symbol rate: {}", info.symbol_rate_min);
    println!("Maximal symbol rate: {}", info.symbol_rate_max);
    println!("Maximal symbol rate tolerance: {}", info.symbol_rate_tolerance);

    let caps: Vec<linuxdvb::caps::FrontendCapsEnum> = info.caps.into();
    println!("Frontend capabilities: {:?}", caps);

    Ok(())
}

fn iterate_devices(adapter_dir: &Path, yet_another_one: bool) -> SimpleResult<bool> {
    let mut has_frontend = false;
    for device in try!(fs::read_dir(adapter_dir)) {
        let device = try!(device);
        let is_frontend = device.path().file_name()
            .map(|f| f.to_str())
            .unwrap_or(None)
            .map_or(false, |f| f.starts_with("frontend"));
        if is_frontend {
            try!(show_frontend_info(&device.path(), yet_another_one));
            has_frontend = true;
        }
    }
    Ok(has_frontend)
}

fn iterate_adapters() -> SimpleResult<bool> {
    let mut has_frontend = false;
    for adapter_dir in try!(fs::read_dir("/dev/dvb")) {
        let adapter_dir = try!(adapter_dir);
        let is_frontend = try!(iterate_devices(&adapter_dir.path(), has_frontend));
        has_frontend = is_frontend || has_frontend;
    }
    Ok(has_frontend)
}

fn main() {
    let has_frontend = match iterate_adapters() {
        Ok(has_frontend) => has_frontend,
        Err(error) => {
            println!("Error: {}", error.description());
            return;
        }
    };
    if !has_frontend {
        println!("No DVB frontend devices were found");
    }
}<commit_msg>Change an unwrap() into try!().<commit_after>// Copyright 2015 Ilkka Rauta
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate linuxdvb;

use std::fs;
use std::error::Error;
use std::path::Path;

use linuxdvb::{Frontend,ReadWriteMode,BlockMode};
use linuxdvb::properties::GetProperty as GP;
use linuxdvb::properties::GetPropertyValue as GPV;

type SimpleResult<T> = Result<T, Box<Error>>;

fn show_frontend_info(path: &Path, yet_another_one: bool) -> SimpleResult<()> {
    let frontend = try!(Frontend::open(path, ReadWriteMode::ReadOnly, BlockMode::NonBlocking));
    if yet_another_one {
        println!("--");
    }
    println!("Device: {}", path.to_string_lossy());
    let info = try!(frontend.get_info());
    println!("Name: {}", info.name);

    let properties = try!(frontend.get_properties(&[
        GP::DtvEnumDelsys
        ]));
    if let GPV::DtvEnumDelsys(delsys) = properties[0] {
        println!("Supported delivery systems: {:?}", delsys.delivery_systems());
    }

    println!("Minimal frequency: {}", info.frequency_min);
    println!("Maximal frequency: {}", info.frequency_max);
    println!("Frequency step: {}", info.frequency_stepsize);
    println!("Frequency tolerance: {}", info.frequency_tolerance);
    println!("Minimal symbol rate: {}", info.symbol_rate_min);
    println!("Maximal symbol rate: {}", info.symbol_rate_max);
    println!("Maximal symbol rate tolerance: {}", info.symbol_rate_tolerance);

    let caps: Vec<linuxdvb::caps::FrontendCapsEnum> = info.caps.into();
    println!("Frontend capabilities: {:?}", caps);

    Ok(())
}

fn iterate_devices(adapter_dir: &Path, yet_another_one: bool) -> SimpleResult<bool> {
    let mut has_frontend = false;
    for device in try!(fs::read_dir(adapter_dir)) {
        let device = try!(device);
        let is_frontend = device.path().file_name()
            .map(|f| f.to_str())
            .unwrap_or(None)
            .map_or(false, |f| f.starts_with("frontend"));
        if is_frontend {
            try!(show_frontend_info(&device.path(), yet_another_one));
            has_frontend = true;
        }
    }
    Ok(has_frontend)
}

fn iterate_adapters() -> SimpleResult<bool> {
    let mut has_frontend = false;
    for adapter_dir in try!(fs::read_dir("/dev/dvb")) {
        let adapter_dir = try!(adapter_dir);
        let is_frontend = try!(iterate_devices(&adapter_dir.path(), has_frontend));
        has_frontend = is_frontend || has_frontend;
    }
    Ok(has_frontend)
}

fn main() {
    let has_frontend = match iterate_adapters() {
        Ok(has_frontend) => has_frontend,
        Err(error) => {
            println!("Error: {}", error.description());
            return;
        }
    };
    if !has_frontend {
        println!("No DVB frontend devices were found");
    }
}<|endoftext|>