Skip to content

Commit

Permalink
Rewrite tests
Browse files Browse the repository at this point in the history
* Add a roundtrip test
* Move comparison tests to tests/building.rs and extend them
* Use fixture RPMs for new tests in tests/parsing.rs
* Consolidate fixture generation scripts
* Add IMA signing to fixtures
* Create dedicated specfiles for exercising various advanced features
* Add more tests for file attrs and capabilities
* Move test_assets/ to tests/assets/
  • Loading branch information
dralley committed Jan 11, 2024
1 parent 440dc70 commit 712a7e5
Show file tree
Hide file tree
Showing 60 changed files with 1,731 additions and 423 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
out
**/*.rpm
Cargo.lock
!test_assets/*
!tests/assets/**
dnf-cache
.idea
.idea
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ serial_test = "3.0"
pretty_assertions = "1.3.0"
gethostname = "0.4"
hex-literal = "0.4"
bstr = "1.4.0"

[features]
default = ["signature-pgp"]
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,24 @@ This library does not build software like rpmbuild. It is meant for finished art
```rust
use rpm::signature::pgp::{Signer, Verifier};

let raw_secret_key = std::fs::read("./test_assets/secret_key.asc")?;
let raw_secret_key = std::fs::read("./tests/assets/signing_keys/secret_ed25519.asc")?;
// It's recommended to use timestamp of last commit in your VCS
let source_date = 1_600_000_000;
let pkg = rpm::PackageBuilder::new("test", "1.0.0", "MIT", "x86_64", "some awesome package")
.compression(rpm::CompressionType::Gzip)
.with_file(
"./test_assets/awesome.toml",
"./tests/assets/SOURCES/example_config.toml",
rpm::FileOptions::new("/etc/awesome/config.toml")
.is_config()
.is_no_replace(),
)?
// file mode is inherited from source file
.with_file(
"./test_assets/awesome.py",
"./tests/assets/SOURCES/multiplication_tables.py",
rpm::FileOptions::new("/usr/bin/awesome"),
)?
.with_file(
"./test_assets/awesome.toml",
"./tests/assets/SOURCES/example_config.toml",
// you can set a custom mode and custom user too
rpm::FileOptions::new("/etc/awesome/second.toml")
.mode(rpm::FileMode::regular(0o644))
Expand Down Expand Up @@ -88,7 +88,7 @@ pkg.write_file("./awesome.rpm")?;

// reading
let raw_pub_key = std::fs::read("/path/to/gpg.key.pub")?;
let pkg = rpm::Package::open("test_assets/389-ds-base-devel-1.3.8.4-15.el7.x86_64.rpm")?;
let pkg = rpm::Package::open("tests/assets/RPMS/signed/noarch/rpm-basic-with-ed25519-2.3.4-5.el9.noarch.rpm")?;

let name = pkg.metadata.get_name()?;
let version = pkg.metadata.get_version()?;
Expand Down
2 changes: 1 addition & 1 deletion src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,7 @@ bitflags! {
const DONOTUSE = 1 << 2; // %%donotuse
const MISSINGOK = 1 << 3; // %%config(missingok)
const NOREPLACE = 1 << 4; // %%config(noreplace)
// const SPECFILE = 1 << 5; // first file in SRPM?
const SPECFILE = 1 << 5; // specfile, which is the first file in a source RPM
const GHOST = 1 << 6; // %%ghost
const LICENSE = 1 << 7; // %%license
const README = 1 << 8; // %%readme
Expand Down
13 changes: 5 additions & 8 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,22 @@
//! # let _ = env_logger::Builder::new().filter_level(log::LevelFilter::Trace).is_test(true).try_init();
//! # #[cfg(feature = "signature-pgp")]
//! # {
//! let raw_secret_key = std::fs::read("./test_assets/secret_key.asc")?;
//! let raw_secret_key = std::fs::read("./tests/assets/signing_keys/secret_rsa4096.asc")?;
//! // It's recommended to use timestamp of last commit in your VCS
//! let source_date = 1_600_000_000;
//! let pkg = rpm::PackageBuilder::new("test", "1.0.0", "MIT", "x86_64", "some awesome package")
//! .compression(rpm::CompressionType::Gzip)
//! .with_file(
//! "./test_assets/awesome.toml",
//! "./tests/assets/SOURCES/example_config.toml",
//! rpm::FileOptions::new("/etc/awesome/config.toml").is_config(),
//! )?
//! // file mode is inherited from source file
//! .with_file(
//! "./test_assets/awesome.py",
//! "./tests/assets/SOURCES/multiplication_tables.py",
//! rpm::FileOptions::new("/usr/bin/awesome"),
//! )?
//! .with_file(
//! "./test_assets/awesome.toml",
//! "./tests/assets/SOURCES/example_config.toml",
//! // you can set a custom mode and custom user too
//! rpm::FileOptions::new("/etc/awesome/second.toml")
//! .mode(rpm::FileMode::regular(0o644))
Expand Down Expand Up @@ -66,7 +66,7 @@
//! pkg.write(&mut f)?;
//!
//! // reading
//! let raw_pub_key = std::fs::read("test_assets/public_key.asc")?;
//! let raw_pub_key = std::fs::read("tests/assets/signing_keys/public_rsa4096.asc")?;
//! let pkg = rpm::Package::open("/tmp/awesome.rpm")?;
//! // verifying
//! pkg.verify_signature(Verifier::load_from_asc_bytes(&raw_pub_key)?)?;
Expand All @@ -85,6 +85,3 @@ pub use crate::constants::*;

mod rpm;
pub use crate::rpm::*;

#[cfg(test)]
mod tests;
12 changes: 6 additions & 6 deletions src/rpm/headers/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use std::{
use super::*;
use crate::{constants::*, errors::*, Timestamp};

#[derive(Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq)]
pub struct Header<T: Tag> {
pub(crate) index_header: IndexHeader,
pub(crate) index_entries: Vec<IndexEntry<T>>,
Expand Down Expand Up @@ -384,8 +384,8 @@ pub struct FileOwnership {

#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct FileDigest {
digest: String,
algo: DigestAlgorithm,
pub digest: String,
pub algo: DigestAlgorithm,
}

impl FileDigest {
Expand Down Expand Up @@ -480,7 +480,7 @@ where
}

/// A header keeping track of all other header records.
#[derive(Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct IndexHeader {
/// rpm specific magic header
pub(crate) magic: [u8; 3],
Expand Down Expand Up @@ -547,7 +547,7 @@ impl IndexHeader {
}

/// A single entry within the [`IndexHeader`](self::IndexHeader)
#[derive(PartialEq)]
#[derive(Clone, PartialEq, Eq)]
pub(crate) struct IndexEntry<T: num::FromPrimitive> {
pub(crate) tag: u32,
pub(crate) data: IndexData,
Expand Down Expand Up @@ -650,7 +650,7 @@ impl<T: Tag> fmt::Display for IndexEntry<T> {
}

/// Data as present in a [`IndexEntry`](self::IndexEntry) .
#[derive(Debug, PartialEq, Eq)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub(crate) enum IndexData {
Null,
Char(Vec<u8>),
Expand Down
2 changes: 1 addition & 1 deletion src/rpm/headers/lead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::errors::*;
/// Used to contain valid data, now only a very limited subset is used
/// and the remaining data is set to fixed values such that compatibility is kept.
/// Only the "magic number" is still relevant as it is used to detect rpm files.
#[derive(Eq)]
#[derive(Clone, Eq)]
pub struct Lead {
magic: [u8; 4],
major: u8,
Expand Down
1 change: 0 additions & 1 deletion src/rpm/headers/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,6 @@ impl<W: std::io::Write> std::io::Write for Sha256Writer<W> {
}

/// Type-alias for a tuple containing index tags for a scriptlet type,
///
pub(crate) type ScriptletIndexTags = (IndexTag, IndexTag, IndexTag);

/// Description of a scriptlet as present in a RPM header record
Expand Down
19 changes: 8 additions & 11 deletions src/rpm/package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub struct Digests {
///
/// Can either be created using the [`PackageBuilder`](crate::PackageBuilder)
/// or used with [`parse`](`self::Package::parse`) to obtain from a file.
#[derive(Debug)]
#[derive(Clone, Debug, PartialEq)]
pub struct Package {
/// Header and metadata structures.
///
Expand Down Expand Up @@ -117,8 +117,8 @@ impl Package {
/// # Examples
/// ```
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let mut package = rpm::Package::open("test_assets/ima_signed.rpm")?;
/// let raw_secret_key = std::fs::read("./test_assets/secret_key.asc")?;
/// let mut package = rpm::Package::open("tests/assets/RPMS/noarch/rpm-basic-2.3.4-5.el9.noarch.rpm")?;
/// let raw_secret_key = std::fs::read("./tests/assets/signing_keys/secret_rsa4096.asc")?;
/// let signer = rpm::signature::pgp::Signer::load_from_asc_bytes(&raw_secret_key)?;
/// // It's recommended to use timestamp of last commit in your VCS
/// let source_date = 1_600_000_000;
Expand Down Expand Up @@ -345,7 +345,7 @@ impl Package {
}
}

#[derive(PartialEq, Debug)]
#[derive(Clone, Debug, PartialEq)]
pub struct PackageMetadata {
pub lead: Lead,
pub signature: Header<IndexSignatureTag>,
Expand Down Expand Up @@ -717,7 +717,7 @@ impl PackageMetadata {
///
/// ```
/// # use rpm::Package;
/// # let package = Package::open("test_assets/389-ds-base-devel-1.3.8.4-15.el7.x86_64.rpm").unwrap();
/// # let package = Package::open("tests/assets/RPMS/noarch/rpm-basic-2.3.4-5.el9.noarch.rpm").unwrap();
/// let offsets = package.metadata.get_package_segment_offsets();
/// let lead = offsets.lead..offsets.signature_header;
/// let sig_header = offsets.signature_header..offsets.header;
Expand Down Expand Up @@ -843,8 +843,7 @@ impl PackageMetadata {

/// The digest algorithm used per file.
///
/// Note that this is not necessarily the same as the digest
/// used for headers.
/// Note that this is not necessarily the same as the digest used for headers.
pub fn get_file_digest_algorithm(&self) -> Result<DigestAlgorithm, Error> {
self.header
.get_entry_data_as_u32(IndexTag::RPMTAG_FILEDIGESTALGO)
Expand Down Expand Up @@ -909,6 +908,7 @@ impl PackageMetadata {
Err(Error::TagNotFound(_)) => Ok(None),
Err(e) => return Err(e),
};
// TODO: verify this is correct behavior for links?
let links = self
.header
.get_entry_data_as_string_array(IndexTag::RPMTAG_FILELINKTOS);
Expand All @@ -918,10 +918,7 @@ impl PackageMetadata {
{
Ok(ima_signatures) => Ok(Some(ima_signatures)),
Err(Error::TagNotFound(_)) => Ok(None),
Err(e) => {
println!("{e:?}");
return Err(e);
}
Err(e) => return Err(e),
};

match (
Expand Down
7 changes: 4 additions & 3 deletions src/rpm/signature/pgp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,9 @@ pub(crate) mod test {

/// Load a pair of sample keys.
pub(crate) fn load_asc_keys() -> (Vec<u8>, Vec<u8>) {
let signing_key = include_bytes!("../../../test_assets/secret_key.asc");
let verification_key = include_bytes!("../../../test_assets/public_key.asc");
let signing_key = include_bytes!("../../../tests/assets/signing_keys/secret_rsa4096.asc");
let verification_key =
include_bytes!("../../../tests/assets/signing_keys/public_rsa4096.asc");
(signing_key.to_vec(), verification_key.to_vec())
}

Expand Down Expand Up @@ -405,7 +406,7 @@ pub(crate) mod test {

#[test]
fn verify_subkeys_match() {
// verifies that all subkeys are present in both keys under test_assets
// verifies that all subkeys are present in both keys under tests/assets/
// which assures all other tests are sane
use std::collections::HashSet;
let (signer, verifier) = prep();
Expand Down
Binary file not shown.
37 changes: 0 additions & 37 deletions test_assets/RPM-GPG-KEY-pmanager

This file was deleted.

8 changes: 0 additions & 8 deletions test_assets/fixture_packages/build_packages.sh

This file was deleted.

18 changes: 0 additions & 18 deletions test_assets/fixture_packages/configure_certs.sh

This file was deleted.

12 changes: 0 additions & 12 deletions test_assets/fixture_packages/create_pgp_pw_protected_keys.sh

This file was deleted.

Binary file removed test_assets/freesrp-udev-0.3.0-1.25.x86_64.rpm
Binary file not shown.
Binary file removed test_assets/ima_signed.rpm
Binary file not shown.
37 changes: 0 additions & 37 deletions test_assets/public_key.asc

This file was deleted.

Binary file removed test_assets/rpm-sign-4.15.1-1.fc31.x86_64.rpm
Binary file not shown.
Loading

0 comments on commit 712a7e5

Please sign in to comment.