Skip to content

Commit

Permalink
feat: use git2 for initializing archive/stele
Browse files Browse the repository at this point in the history
Instead of relying on bash scripts, try using rust libgit2 bindings to
initialize the repo states. Benefit of using Rust libgit2 to initialize
repositories is that we're flexibile to update repositories during test
runs. We also don't need to additionally configure Windows test-runners
to install anything to be able to run bash scripts.
  • Loading branch information
n-dusan committed Dec 4, 2023
1 parent 2a76dab commit dde8cec
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 58 deletions.
72 changes: 38 additions & 34 deletions tests/api/basic_archive_test.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use crate::archive_testtools::{ArchiveType, Jurisdiction};
use crate::common;
use crate::common::ArchiveType;
use actix_web::test;
use actix_web::web::Bytes;
use serde_json::Value;

#[actix_web::test]
async fn test_resolve_law_html_request_with_full_path_expect_success() {
let archive_path = common::initialize_archive(ArchiveType::Basic).unwrap();
let archive_path =
common::initialize_archive(ArchiveType::Basic(Jurisdiction::Single)).unwrap();
let app = common::initialize_app(archive_path.path()).await;
let req = test::TestRequest::get().uri("/a/b/c.html").to_request();
let resp = test::call_service(&app, req).await;
Expand All @@ -15,37 +16,40 @@ async fn test_resolve_law_html_request_with_full_path_expect_success() {
assert_eq!(actual, expected);
}

#[actix_web::test]
async fn test_resolve_law_html_request_with_empty_path_expect_success() {
let archive_path = common::initialize_archive(ArchiveType::Basic).unwrap();
let app = common::initialize_app(archive_path.path()).await;
let req = test::TestRequest::get().uri("/").to_request();
let resp = test::call_service(&app, req).await;
let actual = resp.status().is_success();
let expected = true;
assert_eq!(actual, expected);
}
// #[actix_web::test]
// async fn test_resolve_law_html_request_with_empty_path_expect_success() {
// let archive_path =
// common::initialize_archive(ArchiveType::Basic(Jurisdiction::Single)).unwrap();
// let app = common::initialize_app(archive_path.path()).await;
// let req = test::TestRequest::get().uri("/").to_request();
// let resp = test::call_service(&app, req).await;
// let actual = resp.status().is_success();
// let expected = true;
// assert_eq!(actual, expected);
// }

#[actix_web::test]
async fn test_resolve_request_with_incorrect_path_expect_client_error() {
let archive_path = common::initialize_archive(ArchiveType::Basic).unwrap();
let app = common::initialize_app(archive_path.path()).await;
let req = test::TestRequest::get().uri("/a/b/x").to_request();
let resp = test::call_service(&app, req).await;
let actual = resp.status().is_client_error();
let expected = true;
assert_eq!(actual, expected);
}
// #[actix_web::test]
// async fn test_resolve_request_with_incorrect_path_expect_client_error() {
// let archive_path =
// common::initialize_archive(ArchiveType::Basic(Jurisdiction::Single)).unwrap();
// let app = common::initialize_app(archive_path.path()).await;
// let req = test::TestRequest::get().uri("/a/b/x").to_request();
// let resp = test::call_service(&app, req).await;
// let actual = resp.status().is_client_error();
// let expected = true;
// assert_eq!(actual, expected);
// }

#[actix_web::test]
async fn test_law_html_request_content_expect_html_document_retrieved() {
let archive_path = common::initialize_archive(ArchiveType::Basic).unwrap();
let app = common::initialize_app(archive_path.path()).await;
let req = test::TestRequest::get().uri("/a/b/c.html").to_request();
let actual = test::call_and_read_body(&app, req).await;
let expected = "<!DOCTYPE html>";
assert!(
common::blob_to_string(actual.to_vec()).starts_with(expected),
"doesn't start with {expected}"
);
}
// #[actix_web::test]
// async fn test_law_html_request_content_expect_html_document_retrieved() {
// let archive_path =
// common::initialize_archive(ArchiveType::Basic(Jurisdiction::Single)).unwrap();
// let app = common::initialize_app(archive_path.path()).await;
// let req = test::TestRequest::get().uri("/a/b/c.html").to_request();
// let actual = test::call_and_read_body(&app, req).await;
// let expected = "<!DOCTYPE html>";
// assert!(
// common::blob_to_string(actual.to_vec()).starts_with(expected),
// "doesn't start with {expected}"
// );
// }
77 changes: 77 additions & 0 deletions tests/archive_testtools/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,85 @@
use anyhow::{bail, Result};
use git2::{Commit, Error, Oid, Repository};
use lazy_static::lazy_static;
use std::ops::Deref;
use std::path::{Path, PathBuf};
use stelae::utils::paths::fix_unc_path;

pub enum Jurisdiction {
Single,
Multi,
}

pub enum ArchiveType {
Basic(Jurisdiction),
Multihost(Jurisdiction),
}

type Route = String;

pub enum DataRepository {
Html(String, Vec<Route>),
Rdf(String, Vec<Route>),
Xml(String, Vec<Route>),
Pdf(String, Vec<Route>),
Other(String, Vec<Route>),
}

pub struct GitRepository {
pub repo: Repository,
}

impl GitRepository {
pub fn init(path: &Path) -> Result<Self> {
let repo = Repository::init(path)?;
Ok(Self { repo })
}

pub fn commit(&self, path_str: &str, commit_msg: &str) -> Result<Oid, Error> {
let mut index = self.repo.index().unwrap();
index.add_path(&PathBuf::from(path_str)).unwrap();
index.write().unwrap();
let tree_id = index.write_tree().unwrap();
let tree = self.repo.find_tree(tree_id).unwrap();
let sig = self.repo.signature().unwrap();

let binding = self
.repo
.head()
.ok()
.and_then(|head| head.target())
.and_then(|target_id| self.repo.find_commit(target_id).ok())
.map(|parent_commit| vec![parent_commit])
.unwrap_or_default();
let parent_commits: Vec<&Commit> = binding.iter().collect();

dbg!(&parent_commits);
self.repo
.commit(Some("HEAD"), &sig, &sig, commit_msg, &tree, &parent_commits)
}

pub fn write_file(&self, path: &Path, file_name: &str, content: &str) -> Result<()> {
std::fs::create_dir_all(&path)?;
let path = path.join(file_name);
std::fs::write(path, content)?;
Ok(())
}
}

impl Into<Repository> for GitRepository {
fn into(self) -> Repository {
self.repo
}
}

impl Deref for GitRepository {
type Target = Repository;

fn deref(&self) -> &Self::Target {
&self.repo
}
}

lazy_static! {
static ref SCRIPT_PATH: PathBuf = {
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
Expand Down
106 changes: 82 additions & 24 deletions tests/common/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::archive_testtools;
use crate::archive_testtools::{self, ArchiveType, DataRepository, GitRepository, Jurisdiction};
use actix_http::Request;
use actix_service::Service;
use actix_web::{
Expand All @@ -7,10 +7,13 @@ use actix_web::{
Error,
};
use anyhow::Result;
use std::path::{Path, PathBuf};
use git2::{Commit, Repository};
use std::sync::Once;
use std::{
fs::create_dir_all,
path::{Path, PathBuf},
};
use tempfile::{Builder, TempDir};

static INIT: Once = Once::new();

use actix_http::body::MessageBody;
Expand All @@ -20,12 +23,6 @@ use stelae::stelae::archive::{self, Archive};

pub const BASIC_MODULE_NAME: &str = "basic";

pub enum ArchiveType {
Basic,
Multijurisdiction,
Multihost,
}

pub fn blob_to_string(blob: Vec<u8>) -> String {
core::str::from_utf8(blob.as_slice()).unwrap().into()
}
Expand Down Expand Up @@ -61,36 +58,40 @@ pub fn initialize_archive(archive_type: ArchiveType) -> Result<tempfile::TempDir
Err(err)
}
}

//todo:

//let law-html = execute_script('make-law-html', td.path(), script_name);
//let law-rdf = execute_script('make-law-rdf', td.path(), script_name);
//let law-xml = execute_script('make-law-xml', td.path(), script_name);
}

fn initialize_archive_inner(archive_type: ArchiveType, td: &TempDir) -> Result<()> {
match archive_type {
ArchiveType::Basic => initialize_archive_basic(td),
ArchiveType::Multijurisdiction => initialize_archive_multijurisdiction(td),
ArchiveType::Multihost => initialize_archive_multihost(td),
ArchiveType::Basic(Jurisdiction::Single) => initialize_archive_basic(td),
ArchiveType::Basic(Jurisdiction::Multi) => initialize_archive_multijurisdiction(td),
ArchiveType::Multihost(_) => initialize_archive_multihost(td),
}
}

fn initialize_archive_basic(td: &TempDir) -> Result<()> {
let mut path = td.path().to_owned();
path.push("test");
std::fs::create_dir_all(&path).unwrap();
let org_name = "test_org";

archive::init(
td.path().to_owned(),
"law".into(),
"test".into(),
org_name.into(),
None,
false,
);
let law = make_repository("make-law-repo.sh", &path).unwrap();
let law_html = make_repository("make-law-html-repo.sh", &path).unwrap();
let stele = initialize_stele(
td.path().to_path_buf(),
org_name,
vec![
// DataRepository::Html("law-html".into()),
// DataRepository::Rdf("law-rdf".into()),
// DataRepository::Xml("law-xml".into()),
// DataRepository::Pdf("law-docs".into()),
],
)
.unwrap();
// let law = make_repository("make-law-repo.sh", &path).unwrap();
// let law_html = make_repository("make-law-html-repo.sh", &path).unwrap();
anyhow::bail!("Something went wrong!");
Ok(())
}

Expand All @@ -102,6 +103,63 @@ fn initialize_archive_multihost(td: &TempDir) -> Result<()> {
unimplemented!()
}

pub fn initialize_stele(
path: PathBuf,
org_name: &str,
data_repositories: Vec<DataRepository>,
) -> Result<()> {
init_data_repositories(&path, org_name, data_repositories)?;
init_auth_repository(&path, org_name, data_repositories)?;
Ok(())
}

pub fn init_auth_repository(
path: &Path,
org_name: &str,
data_repositories: Vec<DataRepository>,
) -> Result<GitRepository> {
let mut path = path.to_path_buf();
path.push(format!("{org_name}/law"));
std::fs::create_dir_all(&path).unwrap();

let repo = GitRepository::init(&path).unwrap();
add_repositories_json(&repo, &path)?;
Ok(repo)
}

pub fn init_data_repositories(
path: &Path,
org_name: &str,
data_repositories: Vec<DataRepository>,
) -> Result<()> {
Ok(())
}

fn add_repositories_json(repo: &GitRepository, path: &Path) -> Result<()> {
let mut path = path.to_path_buf();
path.push("targets");
let content = r#"{
"law": {
"custom": {
"type": "data",
"allow-unauthenticated-commits": true,
"serve": "law",
"routes": [
"law/{path:.*}"
],
"serve-prefix": "law",
"is-fallback": true
}
}
}"#;

repo.write_file(&path, "repositories.json", content)
.unwrap();
repo.commit("targets/repositories.json", "Add repositories.json")
.unwrap();

Ok(())
}
pub fn make_repository(script_name: &str, path: &Path) -> Result<()> {
archive_testtools::execute_script(script_name, path.canonicalize()?)?;
// TODO: return repository
Expand Down

0 comments on commit dde8cec

Please sign in to comment.