Skip to content

Commit

Permalink
READY: (willbe): Add Test for Emulation of Publication Sequence (#1481)
Browse files Browse the repository at this point in the history
willbe test
  • Loading branch information
Barsik-sus authored Nov 8, 2024
1 parent 073a878 commit 857016f
Show file tree
Hide file tree
Showing 2 changed files with 309 additions and 0 deletions.
2 changes: 2 additions & 0 deletions module/move/willbe/tests/inc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ mod action_tests;

mod helper;

mod package;

// aaa : for Petro : for Bohdan : for Nikita : sort out test files to be consistent with src files
// sorted

Expand Down
307 changes: 307 additions & 0 deletions module/move/willbe/tests/inc/package.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,310 @@
use std::*;
use std::io::Write;

use crate::the_module::{ action, channel, package };

enum Dependency
{
Normal { name: String, path: Option< path::PathBuf >, is_macro: bool },
Dev { name: String, path: Option< path::PathBuf >, is_macro: bool },
}

impl Dependency
{
fn as_toml( &self ) -> String
{
match self
{
Dependency::Normal { name, path, is_macro } if !is_macro =>
if let Some( path ) = path
{
format!( "[dependencies.{name}]\npath = \"../{}\"", path.display().to_string().replace( "\\", "/" ) )
}
else
{
format!( "[dependencies.{name}]\nversion = \"*\"" )
}
Dependency::Normal { name, .. } => format!( "[dependencies.{name}]\nworkspace = true" ),
Dependency::Dev { name, path, is_macro } if !is_macro =>
if let Some( path ) = path
{
format!( "[dev-dependencies.{name}]\npath = \"../{}\"", path.display().to_string().replace( "\\", "/" ) )
}
else
{
format!( "[dev-dependencies.{name}]\nversion = \"*\"" )
}
Dependency::Dev { name, .. } => format!( "[dev-dependencies.{name}]\nworkspace = true" ),
}
}
}

struct TestPackage
{
name: String,
dependencies: Vec< Dependency >,
path: Option< path::PathBuf >,
}

impl TestPackage
{
pub fn new( name: impl Into< String > ) -> Self
{
Self { name: name.into(), dependencies: vec![], path: None }
}

pub fn dependency( mut self, name: impl Into< String > ) -> Self
{
self.dependencies.push( Dependency::Normal { name: name.into(), path: None, is_macro: false } );
self
}

pub fn macro_dependency( mut self, name: impl Into< String > ) -> Self
{
self.dependencies.push( Dependency::Normal { name: name.into(), path: None, is_macro: true } );
self
}

pub fn dev_dependency( mut self, name: impl Into< String > ) -> Self
{
self.dependencies.push( Dependency::Dev { name: name.into(), path: None, is_macro: false } );
self
}

pub fn macro_dev_dependency( mut self, name: impl Into< String > ) -> Self
{
self.dependencies.push( Dependency::Dev { name: name.into(), path: None, is_macro: true } );
self
}

pub fn create( &mut self, path: impl AsRef< path::Path > ) -> io::Result< () >
{
let path = path.as_ref().join( &self.name );

() = fs::create_dir_all( path.join( "src" ) )?;
() = fs::write( path.join( "src" ).join( "lib.rs" ), &[] )?;

let cargo = format!
(
r#"[package]
name = "{}"
version = "0.1.0"
edition = "2021"
{}"#,
self.name,
self.dependencies.iter().map( Dependency::as_toml ).fold( String::new(), | acc, d |
{
format!( "{acc}\n\n{d}" )
})
);
() = fs::write( path.join( "Cargo.toml" ), cargo.as_bytes() )?;

self.path = Some( path );

Ok( () )
}
}

impl Drop for TestPackage
{
fn drop( &mut self )
{
if let Some( path ) = &self.path
{
_ = fs::remove_dir_all( path ).ok();
}
}
}

struct TestWorkspace
{
packages: Vec< TestPackage >,
path: path::PathBuf,
}

impl TestWorkspace
{
fn new( path: impl AsRef< path::Path > ) -> io::Result< Self >
{
let path = path.as_ref();
() = fs::create_dir_all( path )?;

let cargo = r#"[workspace]
resolver = "2"
members = [
"members/*",
]
"#;
() = fs::write( path.join( "Cargo.toml" ), cargo.as_bytes() )?;

Ok(Self { packages: vec![], path: path.into() })
}

fn find( &self, package_name: impl AsRef< str > ) -> Option< &TestPackage >
{
let name = package_name.as_ref();
self.packages.iter().find( | p | p.name == name )
}

fn with_package( mut self, mut package: TestPackage ) -> io::Result< Self >
{
let mut macro_deps = collections::HashMap::new();
for dep in &mut package.dependencies
{
match dep
{
Dependency::Normal { name, is_macro, .. } if *is_macro =>
{
if let Some( package ) = self.find( &name )
{
if let Some( path ) = &package.path
{
macro_deps.insert( name.clone(), path.clone() );
continue;
}
}
eprintln!( "macro dependency {} not found. required for {}", name, package.name );
}
Dependency::Normal { name, path, .. } =>
{
if let Some( package ) = self.find( &name )
{
if let Some( real_path ) = &package.path
{
let real_path = real_path.strip_prefix( self.path.join( "members" ) ).unwrap_or( real_path );
*path = Some( real_path.into() );
}
}
}
Dependency::Dev { name, is_macro, .. } if *is_macro =>
{
if let Some( package ) = self.find( &name )
{
if let Some( path ) = &package.path
{
macro_deps.insert( name.clone(), path.clone() );
continue;
}
}
eprintln!( "macro dev-dependency {} not found. required for {}", name, package.name );
}
Dependency::Dev { name, path, .. } =>
{
if let Some( package ) = self.find( &name )
{
if let Some( real_path ) = &package.path
{
let real_path = real_path.strip_prefix( self.path.join( "members" ) ).unwrap_or( real_path );
*path = Some( real_path.into() );
}
}
}
}
}
let mut cargo = fs::OpenOptions::new().append( true ).open( self.path.join( "Cargo.toml" ) )?;
for ( name, _ ) in macro_deps
{
writeln!( cargo,
r#"[workspace.dependencies.{name}]
version = "*"
path = "members/{name}""#,
)?;
}
package.create( self.path.join( "members" ) )?;
self.packages.push( package );

Ok( self )
}

fn with_packages( mut self, packages: impl IntoIterator< Item = TestPackage > ) -> io::Result< Self >
{
for package in packages { self = self.with_package( package )?; }

Ok( self )
}
}

impl Drop for TestWorkspace
{
fn drop( &mut self )
{
_ = fs::remove_dir_all( &self.path ).ok();
}
}

#[ test ]
fn kos_plan()
{
let tmp_folder = env::temp_dir().join( "publish_plan_kos_plan" );
_ = fs::remove_dir_all( &tmp_folder ).ok();

let workspace = TestWorkspace::new( tmp_folder ).unwrap()
.with_packages(
[
TestPackage::new( "a" ),
TestPackage::new( "b" ).dependency( "a" ),
TestPackage::new( "c" ).dependency( "a" ),
TestPackage::new( "d" ).dependency( "a" ),
TestPackage::new( "e" ).dependency( "b" ).macro_dev_dependency( "c" ),//.macro_dependency( "c" ),
]).unwrap();
let the_patterns: Vec< String > = workspace
.packages
.iter()
.flat_map( | p | p.path.as_ref().map( | p | p.to_string_lossy().into_owned() ) )
.collect();
dbg!(&the_patterns);

let plan = action::publish_plan
(
the_patterns,
channel::Channel::Stable,
false,
false,
true,
false,
)
.unwrap();

let queue: Vec< &package::PackageName > = plan.plans.iter().map( | i | &i.package_name ).collect();
dbg!(&queue);

// We don’t consider dev dependencies when constructing the project graph, which results in this number of variations.
// If you'd like to modify this behavior, please check `entity/workspace_graph.rs` in the `module_dependency_filter`.
let expected_one_of=
[
[ "a", "b", "d", "c", "e" ],
[ "a", "b", "c", "d", "e" ],
[ "a", "d", "b", "c", "e" ],
[ "a", "c", "b", "d", "e" ],
[ "a", "d", "c", "b", "e" ],
[ "a", "c", "d", "b", "e" ],
[ "a", "b", "d", "e", "c" ],
[ "a", "d", "b", "e", "c" ],
[ "a", "b", "e", "d", "c" ],
[ "a", "e", "b", "d", "c" ],
[ "a", "d", "e", "b", "c" ],
[ "a", "e", "d", "b", "c" ],
[ "a", "b", "c", "e", "d" ],
[ "a", "c", "b", "e", "d" ],
[ "a", "b", "e", "c", "d" ],
[ "a", "e", "b", "c", "d" ],
[ "a", "c", "e", "b", "d" ],
[ "a", "e", "c", "b", "d" ],
];

let mut fail = true;
'sequences: for sequence in expected_one_of
{
for index in 0 .. 5
{
if *queue[ index ] != sequence[ index ].to_string().into() { continue 'sequences; }
}
fail = false;
break;
}
assert!( !fail );
}

// use super::*;
// use the_module::
// {
Expand Down

0 comments on commit 857016f

Please sign in to comment.