ci-cargo

CI for Rust code.
git clone https://git.philomathiclife.com/repos/ci-cargo
Log | Files | Refs | README

tests.rs (61437B)


      1 use super::{
      2     DependenciesErr, FeatureDependenciesErr, Features, FeaturesErr, ImpliedFeaturesErr, Manifest,
      3     ManifestErr, Msrv, NonZeroUsizePlus1, Package, PackageErr, Path, PathBuf, PowerSet,
      4     TooManyFeaturesErr, TryLockError, WorkspaceErr,
      5 };
      6 impl PartialEq for PackageErr {
      7     #[expect(clippy::cognitive_complexity, reason = "long match expression")]
      8     fn eq(&self, other: &Self) -> bool {
      9         match *self {
     10             Self::Missing => matches!(*other, Self::Missing),
     11             Self::InvalidType => matches!(*other, Self::InvalidType),
     12             Self::MissingName => matches!(*other, Self::MissingName),
     13             Self::InvalidNameType => matches!(*other, Self::InvalidNameType),
     14             Self::InvalidMsrvType => matches!(*other, Self::InvalidMsrvType),
     15             Self::Msrv => matches!(*other, Self::Msrv),
     16             Self::MsrvWorkspaceMissing => matches!(*other, Self::MsrvWorkspaceMissing),
     17             Self::MsrvWorkspaceVal => matches!(*other, Self::MsrvWorkspaceVal),
     18             Self::InvalidWorkspaceType => matches!(*other, Self::InvalidWorkspaceType),
     19             Self::WorkspaceIo(ref e) => {
     20                 matches!(*other, Self::WorkspaceIo(ref e2) if e.kind() == e2.kind())
     21             }
     22             Self::WorkspaceLock(ref e) => {
     23                 matches!(*other, Self::WorkspaceLock(ref e2) if match *e {
     24                     TryLockError::Error(ref inner_e) => matches!(*e2, TryLockError::Error(ref inner_e2) if inner_e.kind() == inner_e2.kind()),
     25                     TryLockError::WouldBlock => matches!(*e2, TryLockError::WouldBlock),
     26                 })
     27             }
     28             Self::WorkspaceLenMismatch => matches!(*other, Self::WorkspaceLenMismatch),
     29             Self::WorkspaceDoesNotExist => matches!(*other, Self::WorkspaceDoesNotExist),
     30             Self::WorkspaceRead(ref e, ref p) => {
     31                 matches!(*other, Self::WorkspaceRead(ref e2, ref p2) if e.kind() == e2.kind() && p == p2)
     32             }
     33             Self::WorkspaceReadLock(ref e, ref p) => {
     34                 matches!(*other, Self::WorkspaceReadLock(ref e2, ref p2) if p == p2 && match *e {
     35                     TryLockError::Error(ref inner_e) => matches!(*e2, TryLockError::Error(ref inner_e2) if inner_e.kind() == inner_e2.kind()),
     36                     TryLockError::WouldBlock => matches!(*e2, TryLockError::WouldBlock),
     37                 })
     38             }
     39             Self::WorkspaceReadLenMismatch(ref p) => {
     40                 matches!(*other, Self::WorkspaceReadLenMismatch(ref p2) if p == p2)
     41             }
     42             Self::WorkspaceToml(ref e, ref p) => {
     43                 matches!(*other, Self::WorkspaceToml(ref e2, ref p2) if e == e2 && p == p2)
     44             }
     45             Self::Workspace(e, ref p) => {
     46                 matches!(*other, Self::Workspace(e2, ref p2) if e == e2 && p == p2)
     47             }
     48         }
     49     }
     50 }
     51 #[expect(
     52     clippy::cognitive_complexity,
     53     clippy::too_many_lines,
     54     reason = "want to test a lot of things"
     55 )]
     56 #[test]
     57 fn cargo_toml() {
     58     assert!(
     59         Manifest::from_toml("a".to_owned(), false, Path::new(""), &[])
     60             .map_or_else(|e| matches!(*e, ManifestErr::Toml(_, _)), |_| false)
     61     );
     62     assert_eq!(
     63         Manifest::from_toml(String::new(), false, Path::new(""), &[]),
     64         Err(Box::new(ManifestErr::Package(
     65             PackageErr::Missing,
     66             PathBuf::new()
     67         )))
     68     );
     69     assert_eq!(
     70         Manifest::from_toml("[' package']".to_owned(), false, Path::new(""), &[]),
     71         Err(Box::new(ManifestErr::Package(
     72             PackageErr::Missing,
     73             PathBuf::new()
     74         )))
     75     );
     76     assert_eq!(
     77         Manifest::from_toml("['package ']".to_owned(), false, Path::new(""), &[]),
     78         Err(Box::new(ManifestErr::Package(
     79             PackageErr::Missing,
     80             PathBuf::new()
     81         )))
     82     );
     83     assert_eq!(
     84         Manifest::from_toml("package=2".to_owned(), false, Path::new(""), &[]),
     85         Err(Box::new(ManifestErr::Package(
     86             PackageErr::InvalidType,
     87             PathBuf::new()
     88         )))
     89     );
     90     assert_eq!(
     91         Manifest::from_toml("[package]".to_owned(), false, Path::new(""), &[]),
     92         Err(Box::new(ManifestErr::Package(
     93             PackageErr::MissingName,
     94             PathBuf::new()
     95         )))
     96     );
     97     assert_eq!(
     98         Manifest::from_toml("[package]\nname=true".to_owned(), false, Path::new(""), &[]),
     99         Err(Box::new(ManifestErr::Package(
    100             PackageErr::InvalidNameType,
    101             PathBuf::new()
    102         )))
    103     );
    104     assert_eq!(
    105         Manifest::from_toml(
    106             "[package]\nname=\"\"\n\nrust-version=2".to_owned(),
    107             false,
    108             Path::new(""),
    109             &[]
    110         ),
    111         Err(Box::new(ManifestErr::Package(
    112             PackageErr::InvalidMsrvType,
    113             PathBuf::new()
    114         )))
    115     );
    116     assert_eq!(
    117         Manifest::from_toml(
    118             "[package]\nname=\"\"\nrust-version=\"\"".to_owned(),
    119             false,
    120             Path::new(""),
    121             &[]
    122         ),
    123         Err(Box::new(ManifestErr::Package(
    124             PackageErr::Msrv,
    125             PathBuf::new()
    126         )))
    127     );
    128     assert_eq!(
    129         Manifest::from_toml(
    130             "[package]\nname=\"\"\nrust-version=\"a\"".to_owned(),
    131             false,
    132             Path::new(""),
    133             &[]
    134         ),
    135         Err(Box::new(ManifestErr::Package(
    136             PackageErr::Msrv,
    137             PathBuf::new()
    138         )))
    139     );
    140     assert_eq!(
    141         Manifest::from_toml(
    142             "[package]\nname=\"\"\nrust-version=\"1.00.0\"".to_owned(),
    143             false,
    144             Path::new(""),
    145             &[]
    146         ),
    147         Err(Box::new(ManifestErr::Package(
    148             PackageErr::Msrv,
    149             PathBuf::new()
    150         )))
    151     );
    152     assert_eq!(
    153         Manifest::from_toml(
    154             "[package]\nname=\"\"\nrust-version=\"1..0\"".to_owned(),
    155             false,
    156             Path::new(""),
    157             &[]
    158         ),
    159         Err(Box::new(ManifestErr::Package(
    160             PackageErr::Msrv,
    161             PathBuf::new()
    162         )))
    163     );
    164     assert_eq!(
    165         Manifest::from_toml(
    166             "[package]\nname=\"\"\nrust-version=\"1.\"".to_owned(),
    167             false,
    168             Path::new(""),
    169             &[]
    170         ),
    171         Err(Box::new(ManifestErr::Package(
    172             PackageErr::Msrv,
    173             PathBuf::new()
    174         )))
    175     );
    176     assert_eq!(
    177         Manifest::from_toml(
    178             "[package]\nname=\"\"\nrust-version=\"01.0.0\"".to_owned(),
    179             false,
    180             Path::new(""),
    181             &[]
    182         ),
    183         Err(Box::new(ManifestErr::Package(
    184             PackageErr::Msrv,
    185             PathBuf::new()
    186         )))
    187     );
    188     assert_eq!(
    189         Manifest::from_toml(
    190             "[package]\nname=\"\"\nrust-version=\"1.0.0.1\"".to_owned(),
    191             false,
    192             Path::new(""),
    193             &[]
    194         ),
    195         Err(Box::new(ManifestErr::Package(
    196             PackageErr::Msrv,
    197             PathBuf::new()
    198         )))
    199     );
    200     assert_eq!(
    201         Manifest::from_toml(
    202             "[package]\nname=\"\"\nrust-version=\"111111111111111111111111.2.3\"".to_owned(),
    203             false,
    204             Path::new(""),
    205             &[]
    206         ),
    207         Err(Box::new(ManifestErr::Package(
    208             PackageErr::Msrv,
    209             PathBuf::new()
    210         )))
    211     );
    212     assert_eq!(
    213         Manifest::from_toml(
    214             "[package]\nname=\"\"\nrust-version=\"1.0.0-nightly\"".to_owned(),
    215             false,
    216             Path::new(""),
    217             &[]
    218         ),
    219         Err(Box::new(ManifestErr::Package(
    220             PackageErr::Msrv,
    221             PathBuf::new()
    222         )))
    223     );
    224     assert_eq!(
    225         Manifest::from_toml(
    226             "[package]\nname=\"\"\nrust-version=\"-1.0.0\"".to_owned(),
    227             false,
    228             Path::new(""),
    229             &[]
    230         ),
    231         Err(Box::new(ManifestErr::Package(
    232             PackageErr::Msrv,
    233             PathBuf::new()
    234         )))
    235     );
    236     assert_eq!(
    237         Manifest::from_toml(
    238             "[package]\nname=\"\"\nrust-version=\" 1.0.0\"".to_owned(),
    239             false,
    240             Path::new(""),
    241             &[]
    242         ),
    243         Err(Box::new(ManifestErr::Package(
    244             PackageErr::Msrv,
    245             PathBuf::new()
    246         )))
    247     );
    248     assert_eq!(
    249         Manifest::from_toml(
    250             "[package]\nname=\"\"\nrust-version=\"1.0.0 \"".to_owned(),
    251             false,
    252             Path::new(""),
    253             &[]
    254         ),
    255         Err(Box::new(ManifestErr::Package(
    256             PackageErr::Msrv,
    257             PathBuf::new()
    258         )))
    259     );
    260     assert_eq!(
    261         Manifest::from_toml(
    262             "[package]\nname=\"\"\nrust-version={}".to_owned(),
    263             false,
    264             Path::new(""),
    265             &[]
    266         ),
    267         Err(Box::new(ManifestErr::Package(
    268             PackageErr::MsrvWorkspaceMissing,
    269             PathBuf::new()
    270         )))
    271     );
    272     assert_eq!(
    273         Manifest::from_toml(
    274             "[package]\nname=\"\"\nrust-version={workspace=2}".to_owned(),
    275             false,
    276             Path::new(""),
    277             &[]
    278         ),
    279         Err(Box::new(ManifestErr::Package(
    280             PackageErr::MsrvWorkspaceVal,
    281             PathBuf::new()
    282         )))
    283     );
    284     assert_eq!(
    285         Manifest::from_toml(
    286             "[package]\nname=\"\"\nrust-version={workspace=false}".to_owned(),
    287             false,
    288             Path::new(""),
    289             &[]
    290         ),
    291         Err(Box::new(ManifestErr::Package(
    292             PackageErr::MsrvWorkspaceVal,
    293             PathBuf::new()
    294         )))
    295     );
    296     assert_eq!(
    297         Manifest::from_toml(
    298             "[package]\nname=\"\"\nrust-version={workspace=true}\nworkspace=2".to_owned(),
    299             false,
    300             Path::new(""),
    301             &[]
    302         ),
    303         Err(Box::new(ManifestErr::Package(
    304             PackageErr::InvalidWorkspaceType,
    305             PathBuf::new()
    306         )))
    307     );
    308     assert_eq!(
    309         Manifest::from_toml(
    310             "workspace=2\n[package]\nname=\"\"\nrust-version={workspace=true}".to_owned(),
    311             false,
    312             Path::new(""),
    313             &[]
    314         ),
    315         Err(Box::new(ManifestErr::Package(
    316             PackageErr::Workspace(WorkspaceErr::InvalidType, PathBuf::new()),
    317             PathBuf::new()
    318         )))
    319     );
    320     assert_eq!(
    321         Manifest::from_toml(
    322             "[workspace]\n[package]\nname=\"\"\nrust-version={workspace=true}".to_owned(),
    323             false,
    324             Path::new(""),
    325             &[]
    326         ),
    327         Err(Box::new(ManifestErr::Package(
    328             PackageErr::Workspace(WorkspaceErr::MissingPackage, PathBuf::new()),
    329             PathBuf::new()
    330         )))
    331     );
    332     assert_eq!(
    333         Manifest::from_toml(
    334             "[workspace]\npackage=2\n[package]\nname=\"\"\nrust-version={workspace=true}"
    335                 .to_owned(),
    336             false,
    337             Path::new(""),
    338             &[]
    339         ),
    340         Err(Box::new(ManifestErr::Package(
    341             PackageErr::Workspace(WorkspaceErr::InvalidPackageType, PathBuf::new()),
    342             PathBuf::new()
    343         )))
    344     );
    345     assert_eq!(
    346         Manifest::from_toml(
    347             "[workspace.package]\n[package]\nname=\"\"\nrust-version={workspace=true}".to_owned(),
    348             false,
    349             Path::new(""),
    350             &[]
    351         ),
    352         Err(Box::new(ManifestErr::Package(
    353             PackageErr::Workspace(WorkspaceErr::MissingPackageMsrv, PathBuf::new()),
    354             PathBuf::new()
    355         )))
    356     );
    357     assert_eq!(
    358             Manifest::from_toml(
    359                 "[workspace.package]\nrust-version={}\n[package]\nname=\"\"\nrust-version={workspace=true}"
    360                     .to_owned(),
    361                 false,
    362                 Path::new(""),
    363                 &[]
    364             ),
    365             Err(Box::new(ManifestErr::Package(
    366                 PackageErr::Workspace(WorkspaceErr::InvalidPackageMsrvType, PathBuf::new()),
    367                 PathBuf::new()
    368             )))
    369         );
    370     assert_eq!(
    371             Manifest::from_toml(
    372                 "[workspace.package]\nrust-version=\"\"\n[package]\nname=\"\"\nrust-version={workspace=true}"
    373                     .to_owned(),
    374                 false,
    375                 Path::new(""),
    376                 &[]
    377             ),
    378             Err(Box::new(ManifestErr::Package(
    379                 PackageErr::Workspace(WorkspaceErr::Msrv, PathBuf::new()),
    380                 PathBuf::new()
    381             )))
    382         );
    383     assert_eq!(
    384         Manifest::from_toml(
    385             "features=2\n[package]\nname=\"\"".to_owned(),
    386             false,
    387             Path::new(""),
    388             &[]
    389         ),
    390         Err(Box::new(ManifestErr::Features(
    391             FeaturesErr::InvalidType,
    392             PathBuf::new()
    393         )))
    394     );
    395     assert_eq!(
    396         Manifest::from_toml(
    397             "[features]\n\"/\"=[]\n[package]\nname=\"\"".to_owned(),
    398             false,
    399             Path::new(""),
    400             &[]
    401         ),
    402         Err(Box::new(ManifestErr::Features(
    403             FeaturesErr::InvalidName("/".to_owned()),
    404             PathBuf::new()
    405         )))
    406     );
    407     assert_eq!(
    408         Manifest::from_toml(
    409             "[features]\n\"dep:\"=[]\n[package]\nname=\"\"".to_owned(),
    410             false,
    411             Path::new(""),
    412             &[]
    413         ),
    414         Err(Box::new(ManifestErr::Features(
    415             FeaturesErr::InvalidName("dep:".to_owned()),
    416             PathBuf::new()
    417         )))
    418     );
    419     assert_eq!(
    420         Manifest::from_toml(
    421             "[features]\n\"\"=2\n[package]\nname=\"\"".to_owned(),
    422             false,
    423             Path::new(""),
    424             &[]
    425         ),
    426         Err(Box::new(ManifestErr::Features(
    427             FeaturesErr::FeatureDependencies(FeatureDependenciesErr::InvalidFeatureType(
    428                 String::new()
    429             )),
    430             PathBuf::new()
    431         )))
    432     );
    433     assert_eq!(
    434         Manifest::from_toml(
    435             "[features]\n\"\"=[true]\n[package]\nname=\"\"".to_owned(),
    436             false,
    437             Path::new(""),
    438             &[]
    439         ),
    440         Err(Box::new(ManifestErr::Features(
    441             FeaturesErr::FeatureDependencies(FeatureDependenciesErr::InvalidDependencyType(
    442                 String::new()
    443             )),
    444             PathBuf::new()
    445         )))
    446     );
    447     assert_eq!(
    448         Manifest::from_toml(
    449             "[features]\n\"\"=[\"foo\"]\n[package]\nname=\"\"".to_owned(),
    450             false,
    451             Path::new(""),
    452             &[]
    453         ),
    454         Err(Box::new(ManifestErr::Features(
    455             FeaturesErr::FeatureDependencies(FeatureDependenciesErr::InvalidDependency(
    456                 String::new(),
    457                 "foo".to_owned()
    458             )),
    459             PathBuf::new()
    460         )))
    461     );
    462     // Feature dependencies can't be implied features when implied features are forbidden.
    463     assert_eq!(
    464         Manifest::from_toml(
    465             "[dependencies]\nfoo={optional=true}\n[features]\n\"\"=[\"foo\"]\n[package]\nname=\"\""
    466                 .to_owned(),
    467             false,
    468             Path::new(""),
    469             &[]
    470         ),
    471         Err(Box::new(ManifestErr::Features(
    472             FeaturesErr::FeatureDependencies(FeatureDependenciesErr::InvalidDependency(
    473                 String::new(),
    474                 "foo".to_owned()
    475             )),
    476             PathBuf::new()
    477         )))
    478     );
    479     assert_eq!(
    480         Manifest::from_toml(
    481             "[features]\n\"\"=[\"\"]\n[package]\nname=\"\"".to_owned(),
    482             false,
    483             Path::new(""),
    484             &[]
    485         ),
    486         Err(Box::new(ManifestErr::Features(
    487             FeaturesErr::FeatureDependencies(FeatureDependenciesErr::CyclicFeature(String::new())),
    488             PathBuf::new()
    489         )))
    490     );
    491     assert_eq!(
    492         Manifest::from_toml(
    493             "[features]\n\"\"=[\"a\"]\na=[\"\"]\n[package]\nname=\"\"".to_owned(),
    494             false,
    495             Path::new(""),
    496             &[]
    497         ),
    498         Err(Box::new(ManifestErr::Features(
    499             FeaturesErr::FeatureDependencies(FeatureDependenciesErr::CyclicFeature(String::new())),
    500             PathBuf::new()
    501         )))
    502     );
    503     assert_eq!(
    504         Manifest::from_toml(
    505             "[features]\n\"\"=[\"a\"]\na=[\"b\"]\nb=[\"a\"]\n[package]\nname=\"\"".to_owned(),
    506             false,
    507             Path::new(""),
    508             &[]
    509         ),
    510         Err(Box::new(ManifestErr::Features(
    511             FeaturesErr::FeatureDependencies(FeatureDependenciesErr::CyclicFeature("a".to_owned())),
    512             PathBuf::new()
    513         )))
    514     );
    515     assert_eq!(
    516         Manifest::from_toml(
    517             "[features]\n\"\"=[\"a\"]\na=[\"c\",\"b\"]\nb=[\"a\"]\nc=[]\n[package]\nname=\"\""
    518                 .to_owned(),
    519             false,
    520             Path::new(""),
    521             &[]
    522         ),
    523         Err(Box::new(ManifestErr::Features(
    524             FeaturesErr::FeatureDependencies(FeatureDependenciesErr::CyclicFeature("a".to_owned())),
    525             PathBuf::new()
    526         )))
    527     );
    528     assert_eq!(
    529         Manifest::from_toml(
    530             "[features]\n\"\"=[]\na=[\"c\",\"b\"]\nb=[\"a\"]\nc=[]\n[package]\nname=\"\""
    531                 .to_owned(),
    532             false,
    533             Path::new(""),
    534             &[]
    535         ),
    536         Err(Box::new(ManifestErr::Features(
    537             FeaturesErr::FeatureDependencies(FeatureDependenciesErr::CyclicFeature("a".to_owned())),
    538             PathBuf::new()
    539         )))
    540     );
    541     assert_eq!(
    542         Manifest::from_toml(
    543             "[features]\n\"\"=[\"a\",\"b\"]\na=[\"b\"]\nb=[]\n[package]\nname=\"\"".to_owned(),
    544             false,
    545             Path::new(""),
    546             &[]
    547         ),
    548         Err(Box::new(ManifestErr::Features(
    549             FeaturesErr::FeatureDependencies(FeatureDependenciesErr::RedundantDependency(
    550                 String::new(),
    551                 "b".to_owned()
    552             )),
    553             PathBuf::new()
    554         )))
    555     );
    556     assert_eq!(
    557         Manifest::from_toml(
    558             "[features]\n\"\"=[\"a\",\"a\"]\na=[]\n[package]\nname=\"\"".to_owned(),
    559             false,
    560             Path::new(""),
    561             &[]
    562         ),
    563         Err(Box::new(ManifestErr::Features(
    564             FeaturesErr::FeatureDependencies(FeatureDependenciesErr::RedundantDependency(
    565                 String::new(),
    566                 "a".to_owned()
    567             )),
    568             PathBuf::new()
    569         )))
    570     );
    571     // Duplicate `"dep:"` feature dependencies error.
    572     assert_eq!(
    573         Manifest::from_toml(
    574             "[features]\n\"\"=[\"dep:\",\"dep:\"]\na=[]\n[package]\nname=\"\"".to_owned(),
    575             false,
    576             Path::new(""),
    577             &[]
    578         ),
    579         Err(Box::new(ManifestErr::Features(
    580             FeaturesErr::FeatureDependencies(FeatureDependenciesErr::RedundantDependency(
    581                 String::new(),
    582                 "dep:".to_owned()
    583             )),
    584             PathBuf::new()
    585         )))
    586     );
    587     assert_eq!(
    588         Manifest::from_toml(
    589             "target=2\n[package]\nname=\"\"".to_owned(),
    590             false,
    591             Path::new(""),
    592             &[]
    593         ),
    594         Err(Box::new(ManifestErr::ImpliedFeatures(
    595             ImpliedFeaturesErr::TargetType,
    596             PathBuf::new()
    597         )))
    598     );
    599     assert_eq!(
    600         Manifest::from_toml(
    601             "dependencies=2\n[package]\nname=\"\"".to_owned(),
    602             false,
    603             Path::new(""),
    604             &[]
    605         ),
    606         Err(Box::new(ManifestErr::ImpliedFeatures(
    607             ImpliedFeaturesErr::Dependencies(DependenciesErr::Type("dependencies")),
    608             PathBuf::new()
    609         )))
    610     );
    611     assert_eq!(
    612         Manifest::from_toml(
    613             "build-dependencies=2\n[package]\nname=\"\"".to_owned(),
    614             false,
    615             Path::new(""),
    616             &[]
    617         ),
    618         Err(Box::new(ManifestErr::ImpliedFeatures(
    619             ImpliedFeaturesErr::Dependencies(DependenciesErr::Type("build-dependencies")),
    620             PathBuf::new(),
    621         )))
    622     );
    623     assert_eq!(
    624         Manifest::from_toml(
    625             "[dependencies]\n\"dep:\"=\"\"\n[package]\nname=\"\"".to_owned(),
    626             false,
    627             Path::new(""),
    628             &[]
    629         ),
    630         Err(Box::new(ManifestErr::ImpliedFeatures(
    631             ImpliedFeaturesErr::Dependencies(DependenciesErr::Name(
    632                 "dependencies",
    633                 "dep:".to_owned()
    634             )),
    635             PathBuf::new(),
    636         )))
    637     );
    638     assert_eq!(
    639         Manifest::from_toml(
    640             "[dependencies]\n\"/\"=\"\"\n[package]\nname=\"\"".to_owned(),
    641             false,
    642             Path::new(""),
    643             &[]
    644         ),
    645         Err(Box::new(ManifestErr::ImpliedFeatures(
    646             ImpliedFeaturesErr::Dependencies(DependenciesErr::Name("dependencies", "/".to_owned())),
    647             PathBuf::new(),
    648         )))
    649     );
    650     assert_eq!(
    651         Manifest::from_toml(
    652             "[build-dependencies]\n\"dep:\"=\"\"\n[package]\nname=\"\"".to_owned(),
    653             false,
    654             Path::new(""),
    655             &[]
    656         ),
    657         Err(Box::new(ManifestErr::ImpliedFeatures(
    658             ImpliedFeaturesErr::Dependencies(DependenciesErr::Name(
    659                 "build-dependencies",
    660                 "dep:".to_owned()
    661             )),
    662             PathBuf::new(),
    663         )))
    664     );
    665     assert_eq!(
    666         Manifest::from_toml(
    667             "[build-dependencies]\n\"/\"=\"\"\n[package]\nname=\"\"".to_owned(),
    668             false,
    669             Path::new(""),
    670             &[]
    671         ),
    672         Err(Box::new(ManifestErr::ImpliedFeatures(
    673             ImpliedFeaturesErr::Dependencies(DependenciesErr::Name(
    674                 "build-dependencies",
    675                 "/".to_owned()
    676             )),
    677             PathBuf::new(),
    678         )))
    679     );
    680     assert_eq!(
    681         Manifest::from_toml(
    682             "[dependencies]\n\"\"=2\n[package]\nname=\"\"".to_owned(),
    683             false,
    684             Path::new(""),
    685             &[]
    686         ),
    687         Err(Box::new(ManifestErr::ImpliedFeatures(
    688             ImpliedFeaturesErr::Dependencies(DependenciesErr::DependencyType(
    689                 "dependencies",
    690                 String::new()
    691             )),
    692             PathBuf::new(),
    693         )))
    694     );
    695     assert_eq!(
    696         Manifest::from_toml(
    697             "[build-dependencies]\n\"\"=2\n[package]\nname=\"\"".to_owned(),
    698             false,
    699             Path::new(""),
    700             &[]
    701         ),
    702         Err(Box::new(ManifestErr::ImpliedFeatures(
    703             ImpliedFeaturesErr::Dependencies(DependenciesErr::DependencyType(
    704                 "build-dependencies",
    705                 String::new()
    706             )),
    707             PathBuf::new(),
    708         )))
    709     );
    710     assert_eq!(
    711         Manifest::from_toml(
    712             "[dependencies]\n\"\"={optional=2}\n[package]\nname=\"\"".to_owned(),
    713             false,
    714             Path::new(""),
    715             &[]
    716         ),
    717         Err(Box::new(ManifestErr::ImpliedFeatures(
    718             ImpliedFeaturesErr::Dependencies(DependenciesErr::OptionalType(
    719                 "dependencies",
    720                 String::new()
    721             )),
    722             PathBuf::new(),
    723         )))
    724     );
    725     assert_eq!(
    726         Manifest::from_toml(
    727             "[build-dependencies]\n\"\"={optional=2}\n[package]\nname=\"\"".to_owned(),
    728             false,
    729             Path::new(""),
    730             &[]
    731         ),
    732         Err(Box::new(ManifestErr::ImpliedFeatures(
    733             ImpliedFeaturesErr::Dependencies(DependenciesErr::OptionalType(
    734                 "build-dependencies",
    735                 String::new()
    736             )),
    737             PathBuf::new(),
    738         )))
    739     );
    740     // Implied features are disallowed iff `!allow_implied_features`.
    741     assert_eq!(
    742         Manifest::from_toml(
    743             "[dependencies]\nfoo={optional=true}\n[package]\nname=\"\"".to_owned(),
    744             false,
    745             Path::new(""),
    746             &[]
    747         ),
    748         Err(Box::new(ManifestErr::ImpliedFeatures(
    749             ImpliedFeaturesErr::Dependencies(DependenciesErr::ImpliedFeature(
    750                 "dependencies",
    751                 "foo".to_owned()
    752             )),
    753             PathBuf::new(),
    754         )))
    755     );
    756     assert_eq!(
    757         Manifest::from_toml(
    758             "[target]\n\"\"=2\n[package]\nname=\"\"".to_owned(),
    759             false,
    760             Path::new(""),
    761             &[]
    762         ),
    763         Err(Box::new(ManifestErr::ImpliedFeatures(
    764             ImpliedFeaturesErr::TargetPlatformType(String::new()),
    765             PathBuf::new(),
    766         )))
    767     );
    768     assert_eq!(
    769         Manifest::from_toml(
    770             "[target.\"\"]\ndependencies=2\n[package]\nname=\"\"".to_owned(),
    771             false,
    772             Path::new(""),
    773             &[]
    774         ),
    775         Err(Box::new(ManifestErr::ImpliedFeatures(
    776             ImpliedFeaturesErr::TagetPlatformDependencies(
    777                 String::new(),
    778                 DependenciesErr::Type("dependencies")
    779             ),
    780             PathBuf::new(),
    781         )))
    782     );
    783     assert_eq!(
    784         Manifest::from_toml(
    785             "[target.\"\"]\nbuild-dependencies=2\n[package]\nname=\"\"".to_owned(),
    786             false,
    787             Path::new(""),
    788             &[]
    789         ),
    790         Err(Box::new(ManifestErr::ImpliedFeatures(
    791             ImpliedFeaturesErr::TagetPlatformDependencies(
    792                 String::new(),
    793                 DependenciesErr::Type("build-dependencies")
    794             ),
    795             PathBuf::new(),
    796         )))
    797     );
    798     assert_eq!(
    799         Manifest::from_toml(
    800             "[target.\"\".dependencies]\n\"/\"=\"\"\n[package]\nname=\"\"".to_owned(),
    801             false,
    802             Path::new(""),
    803             &[]
    804         ),
    805         Err(Box::new(ManifestErr::ImpliedFeatures(
    806             ImpliedFeaturesErr::TagetPlatformDependencies(
    807                 String::new(),
    808                 DependenciesErr::Name("dependencies", "/".to_owned())
    809             ),
    810             PathBuf::new(),
    811         )))
    812     );
    813     assert_eq!(
    814         Manifest::from_toml(
    815             "[target.\"\".dependencies]\n\"dep:\"=\"\"\n[package]\nname=\"\"".to_owned(),
    816             false,
    817             Path::new(""),
    818             &[]
    819         ),
    820         Err(Box::new(ManifestErr::ImpliedFeatures(
    821             ImpliedFeaturesErr::TagetPlatformDependencies(
    822                 String::new(),
    823                 DependenciesErr::Name("dependencies", "dep:".to_owned())
    824             ),
    825             PathBuf::new(),
    826         )))
    827     );
    828     assert_eq!(
    829         Manifest::from_toml(
    830             "[target.\"\".build-dependencies]\n\"/\"=\"\"\n[package]\nname=\"\"".to_owned(),
    831             false,
    832             Path::new(""),
    833             &[]
    834         ),
    835         Err(Box::new(ManifestErr::ImpliedFeatures(
    836             ImpliedFeaturesErr::TagetPlatformDependencies(
    837                 String::new(),
    838                 DependenciesErr::Name("build-dependencies", "/".to_owned())
    839             ),
    840             PathBuf::new(),
    841         )))
    842     );
    843     assert_eq!(
    844         Manifest::from_toml(
    845             "[target.\"\".build-dependencies]\n\"dep:\"=\"\"\n[package]\nname=\"\"".to_owned(),
    846             false,
    847             Path::new(""),
    848             &[]
    849         ),
    850         Err(Box::new(ManifestErr::ImpliedFeatures(
    851             ImpliedFeaturesErr::TagetPlatformDependencies(
    852                 String::new(),
    853                 DependenciesErr::Name("build-dependencies", "dep:".to_owned())
    854             ),
    855             PathBuf::new(),
    856         )))
    857     );
    858     assert_eq!(
    859         Manifest::from_toml(
    860             "[target.\"\".dependencies]\n\"\"=false\n[package]\nname=\"\"".to_owned(),
    861             false,
    862             Path::new(""),
    863             &[]
    864         ),
    865         Err(Box::new(ManifestErr::ImpliedFeatures(
    866             ImpliedFeaturesErr::TagetPlatformDependencies(
    867                 String::new(),
    868                 DependenciesErr::DependencyType("dependencies", String::new())
    869             ),
    870             PathBuf::new(),
    871         )))
    872     );
    873     assert_eq!(
    874         Manifest::from_toml(
    875             "[target.\"\".build-dependencies]\n\"\"=false\n[package]\nname=\"\"".to_owned(),
    876             false,
    877             Path::new(""),
    878             &[]
    879         ),
    880         Err(Box::new(ManifestErr::ImpliedFeatures(
    881             ImpliedFeaturesErr::TagetPlatformDependencies(
    882                 String::new(),
    883                 DependenciesErr::DependencyType("build-dependencies", String::new())
    884             ),
    885             PathBuf::new(),
    886         )))
    887     );
    888     assert_eq!(
    889         Manifest::from_toml(
    890             "[target.\"\".dependencies]\n\"\"={optional=2}\n[package]\nname=\"\"".to_owned(),
    891             false,
    892             Path::new(""),
    893             &[]
    894         ),
    895         Err(Box::new(ManifestErr::ImpliedFeatures(
    896             ImpliedFeaturesErr::TagetPlatformDependencies(
    897                 String::new(),
    898                 DependenciesErr::OptionalType("dependencies", String::new())
    899             ),
    900             PathBuf::new(),
    901         )))
    902     );
    903     assert_eq!(
    904         Manifest::from_toml(
    905             "[target.\"\".build-dependencies]\n\"\"={optional=2}\n[package]\nname=\"\"".to_owned(),
    906             false,
    907             Path::new(""),
    908             &[]
    909         ),
    910         Err(Box::new(ManifestErr::ImpliedFeatures(
    911             ImpliedFeaturesErr::TagetPlatformDependencies(
    912                 String::new(),
    913                 DependenciesErr::OptionalType("build-dependencies", String::new())
    914             ),
    915             PathBuf::new(),
    916         )))
    917     );
    918     // An invalid dependency error occurs later when we `allow_implied_features` since
    919     // implied features aren't added until after feature extraction.
    920     assert_eq!(
    921         Manifest::from_toml(
    922             "[features]\n\"\"=[\"foo\"]\n[package]\nname=\"\"".to_owned(),
    923             true,
    924             Path::new(""),
    925             &[]
    926         ),
    927         Err(Box::new(ManifestErr::ImpliedFeatures(
    928             ImpliedFeaturesErr::InvalidDependency(String::new(), "foo".to_owned()),
    929             PathBuf::new(),
    930         )))
    931     );
    932     // In contrast, above would have erred sooner if `!allow_implied_features`.
    933     assert_eq!(
    934         Manifest::from_toml(
    935             "[features]\n\"\"=[\"foo\"]\n[package]\nname=\"\"".to_owned(),
    936             false,
    937             Path::new(""),
    938             &[]
    939         ),
    940         Err(Box::new(ManifestErr::Features(
    941             FeaturesErr::FeatureDependencies(FeatureDependenciesErr::InvalidDependency(
    942                 String::new(),
    943                 "foo".to_owned()
    944             )),
    945             PathBuf::new()
    946         )))
    947     );
    948     assert_eq!(
    949         Manifest::from_toml(
    950             "[package]\nname=\"\"".to_owned(),
    951             false,
    952             Path::new(""),
    953             &["a".to_owned()]
    954         ),
    955         Err(Box::new(ManifestErr::UndefinedIgnoreFeature(
    956             "a".to_owned(),
    957             PathBuf::new()
    958         )))
    959     );
    960     // Even if we forbid implied features, we don't error when a feature is defined
    961     // with the same name of an implied feature. This is due to simplicity in code
    962     // and the fact that `cargo` will error anyway.
    963     //
    964     // For example once `cargo` is invoked, an error will occur due to duplicate features:
    965     // the explict feature `foo` and the implied feature from the dependency `foo`.
    966     assert_eq!(
    967         Manifest::from_toml(
    968             "[dependencies]\nfoo={optional=true}\n[features]\nfoo=[]\n[package]\nname=\"\""
    969                 .to_owned(),
    970             false,
    971             Path::new(""),
    972             &[]
    973         ),
    974         Ok(Manifest {
    975             package: Package {
    976                 msrv: None,
    977                 name: String::new(),
    978             },
    979             features: Features(vec![("foo".to_owned(), Vec::new())]),
    980         })
    981     );
    982     // Allow major-only MSRV.
    983     assert_eq!(
    984         Manifest::from_toml(
    985             "[package]\nname=\"foo\"\nrust-version=\"0\"".to_owned(),
    986             false,
    987             Path::new(""),
    988             &[]
    989         ),
    990         Ok(Manifest {
    991             package: Package {
    992                 msrv: Some(Msrv {
    993                     major: 0,
    994                     minor: None,
    995                     patch: None,
    996                 }),
    997                 name: "foo".to_owned(),
    998             },
    999             features: Features(Vec::new()),
   1000         })
   1001     );
   1002     // Allow escapes.
   1003     assert_eq!(
   1004             Manifest::from_toml(
   1005                 "[\"\\u0070ackage\"]\n\"n\\u0061me\"=\"\\u0066oo\"\n\"\\u0072ust-version\"=\"0\\u002E\\u0031\"".to_owned(),
   1006                 false,
   1007                 Path::new(""),
   1008                 &[]
   1009             ),
   1010             Ok(Manifest {
   1011                 package: Package {
   1012                     msrv: Some(Msrv {
   1013                         major: 0,
   1014                         minor: Some(1),
   1015                         patch: None,
   1016                     }),
   1017                     name: "foo".to_owned(),
   1018                 },
   1019                 features: Features(Vec::new()),
   1020             })
   1021         );
   1022     assert_eq!(
   1023         Manifest::from_toml(
   1024             "[package]\nname=\"\"\nrust-version=\"0.0.0\"".to_owned(),
   1025             false,
   1026             Path::new(""),
   1027             &[]
   1028         ),
   1029         Ok(Manifest {
   1030             package: Package {
   1031                 msrv: Some(Msrv {
   1032                     major: 0,
   1033                     minor: Some(0),
   1034                     patch: Some(0),
   1035                 }),
   1036                 name: String::new(),
   1037             },
   1038             features: Features(Vec::new()),
   1039         })
   1040     );
   1041     // Ignore non `rust-version` keys in `package`. Ignore keys in the root document except `package`,
   1042     // `features`, `dependencies`, `build-dependencies`, and `target`. Ignore keys in
   1043     // `target.<something>` unless the key is `dependencies` or `build-dependencies`. Don't treat
   1044     // `<something>` special in `target.<something>` other than its being a table.
   1045     assert_eq!(
   1046             Manifest::from_toml("dev-dependencies=2\n[package]\nname=\"\"\n\nfoo=2\nrust-version=\"18446744073709551615.18446744073709551615.18446744073709551615\"\n[foo]\nbar=false\n[target.\"\".foo]\nbar=2\n[target.foo]\nbar=false\n[target.dependencies]\nfoo=2\n[target.build-dependencies]\nfoo=false\n[target.dev-dependencies]\nfoo=true\n".to_owned(), false, Path::new(""), &[]),
   1047             Ok(Manifest {
   1048                 package: Package {
   1049                     msrv: Some(Msrv {
   1050                         major: u64::MAX,
   1051                         minor: Some(u64::MAX),
   1052                         patch: Some(u64::MAX),
   1053                     }),
   1054                     name: String::new(),
   1055                 },
   1056                 features: Features(Vec::new()),
   1057             })
   1058         );
   1059     // [package]
   1060     // name = ""
   1061     //
   1062     // ["\u0064ependencies"]
   1063     // "\u0000" = "\u0000"
   1064     // a = { optional = true }
   1065     //
   1066     // ["build-\u0064ependencies"]
   1067     // "\u0000" = { optional = true }
   1068     //
   1069     // [dev-dependencies]
   1070     // buzz = { optional = true }
   1071     //
   1072     // [target."".dependencies]
   1073     // b = { optional = false, foo = 2 }
   1074     // fizz = { optional = true, foo = 3 }
   1075     //
   1076     // [target.a.dependencies]
   1077     // c = { optional = true }
   1078     // wuzz = { optional = true }
   1079     //
   1080     // [features]
   1081     // default = ["bar","dep:lk","a/ak", "a/ak"]
   1082     // bar = ["dep\u003Awuzz"]
   1083     //
   1084     // We allow any and all key names unless it's the features table or a dependency table; in which case
   1085     // key names must not contain `'/'` nor begin with `"dep:"`.
   1086     //
   1087     // The order of features is based on the following hierarchy:
   1088     // * Explict features: lexicographically sorted
   1089     // * dependencies: optional only, lexicographically sorted, only if an explicit feature doesn't exist with
   1090     //   the same name nor any explicit feature contains a dependency named `"dep:<dependecy>"` and we allow
   1091     //   implied features. If such feature exists, we don't error but simply don't add.
   1092     // * build-dependencies: read above.
   1093     // * target.<something>: lexicographically sorted by something, within `something`, `dependencies`
   1094     //   is first using the same methodology as item 2, last `build-dependencies`.
   1095     //
   1096     // Once the order of features is determined, the only feature dependencies that are retained are those
   1097     // that don't contain `'/'` nor begin with `"dep:"`. We don't require dependencies to be defined for
   1098     // feature dependencies that contain `'/'` or begin with `"dep:"`. We don't care about duplicate feature
   1099     // dependencies that contain `'/'`.
   1100     //
   1101     // Based on above, `Features` looks like the following:
   1102     // 1. (bar, [])
   1103     // 2. (default, ["bar"])
   1104     // 3. (a, [])
   1105     // 4. (\x00, [])
   1106     // 5. (fizz, [])
   1107     // 6. (c, [])
   1108     assert_eq!(
   1109             Manifest::from_toml(
   1110                 "[\"\\u0064ependencies\"]\n\"\\u0000\"=\"\\u0000\"\na={optional=true}\n[\"build-\\u0064ependencies\"]\n\"\\u0000\"={optional=true}\n[target.\"\".dependencies]\nb={optional=false,foo=2}\nfizz={optional=true,foo=3}\n[features]\ndefault=[\"bar\",\"dep:lk\",\"a/ak\",\"a/ak\"]\nbar=[\"dep\\u003Awuzz\"]\n[dev-dependencies]\nbuzz={optional=true}\n[target.a.dependencies]\nc={optional=true}\nwuzz={optional=true}\n[package]\nname=\"\"".to_owned(),
   1111                 true,
   1112                 Path::new(""),
   1113                 &[]
   1114             ),
   1115             Ok(Manifest {
   1116                 package: Package {
   1117                     msrv: None,
   1118                     name: String::new(),
   1119                 },
   1120                 features: Features(vec![("bar".to_owned(), Vec::new()), ("default".to_owned(), vec!["bar".to_owned()]), ("a".to_owned(), Vec::new()), ("\0".to_owned(), Vec::new()), ("fizz".to_owned(), Vec::new()), ("c".to_owned(), Vec::new())]),
   1121             })
   1122         );
   1123     // [package]
   1124     // name = ""
   1125     //
   1126     // [dependencies]
   1127     // foo = { "optional" = true }
   1128     // fizz = { "optional" = true }
   1129     //
   1130     // [features]
   1131     // fizz = ["dep:fizz"]
   1132     // bar = ["dep:foo"]
   1133     assert_eq!(
   1134             Manifest::from_toml(
   1135                 "[package]\nname=\"\"\n[dependencies]\nfoo={optional=true}\nfizz={optional=true}\n[features]\nfizz=[\"dep:fizz\"]\nbar=[\"dep:foo\"]".to_owned(),
   1136                 false,
   1137                 Path::new(""),
   1138                 &[]
   1139             ),
   1140             Ok(Manifest {
   1141                 package: Package {
   1142                     msrv: None,
   1143                     name: String::new(),
   1144                 },
   1145                 features: Features(vec![
   1146                     ("bar".to_owned(), Vec::new()),
   1147                     ("fizz".to_owned(), Vec::new())
   1148                 ]),
   1149             })
   1150         );
   1151     // [package]
   1152     // name = ""
   1153     //
   1154     // [dependencies]
   1155     // bar = { "optional" = true }
   1156     //
   1157     // [features]
   1158     // foo = ["bar"]
   1159     assert_eq!(
   1160         Manifest::from_toml(
   1161             "[package]\nname=\"\"\n[dependencies]\nbar={optional=true}\n[features]\nfoo=[\"bar\"]"
   1162                 .to_owned(),
   1163             true,
   1164             Path::new(""),
   1165             &[]
   1166         ),
   1167         Ok(Manifest {
   1168             package: Package {
   1169                 msrv: None,
   1170                 name: String::new(),
   1171             },
   1172             features: Features(vec![
   1173                 ("foo".to_owned(), vec!["bar".to_owned()]),
   1174                 ("bar".to_owned(), Vec::new()),
   1175             ]),
   1176         })
   1177     );
   1178     assert_eq!(
   1179         Manifest::from_toml(
   1180             "[package]\nname=\"\"\n[features]\na=[]\nb=[\"a\"]".to_owned(),
   1181             false,
   1182             Path::new(""),
   1183             &["a".to_owned()]
   1184         ),
   1185         Ok(Manifest {
   1186             package: Package {
   1187                 msrv: None,
   1188                 name: String::new(),
   1189             },
   1190             features: Features(vec![]),
   1191         })
   1192     );
   1193     assert_eq!(
   1194         Manifest::from_toml(
   1195             "[package]\nname=\"\"\n[features]\na=[]\nb=[\"a\"]".to_owned(),
   1196             false,
   1197             Path::new(""),
   1198             &["b".to_owned()]
   1199         ),
   1200         Ok(Manifest {
   1201             package: Package {
   1202                 msrv: None,
   1203                 name: String::new(),
   1204             },
   1205             features: Features(vec![("a".to_owned(), Vec::new())]),
   1206         })
   1207     );
   1208     assert_eq!(
   1209         Manifest::from_toml(
   1210             "[package]\nname=\"\"\n[dependencies]\nc={optional=true}\n[features]\nb=[\"c\"]"
   1211                 .to_owned(),
   1212             true,
   1213             Path::new(""),
   1214             &["c".to_owned()]
   1215         ),
   1216         Ok(Manifest {
   1217             package: Package {
   1218                 msrv: None,
   1219                 name: String::new(),
   1220             },
   1221             features: Features(vec![]),
   1222         })
   1223     );
   1224     assert_eq!(
   1225         Manifest::from_toml(
   1226             "[package]\nname=\"\"\n[dependencies]\nc={optional=true}\n[features]\nb=[\"c\"]"
   1227                 .to_owned(),
   1228             true,
   1229             Path::new(""),
   1230             &["b".to_owned()]
   1231         ),
   1232         Ok(Manifest {
   1233             package: Package {
   1234                 msrv: None,
   1235                 name: String::new(),
   1236             },
   1237             features: Features(vec![("c".to_owned(), Vec::new())]),
   1238         })
   1239     );
   1240 }
   1241 #[expect(clippy::unreachable, reason = "want to crash when there is a bug")]
   1242 #[expect(
   1243     clippy::cognitive_complexity,
   1244     clippy::too_many_lines,
   1245     reason = "want to test for a lot of things"
   1246 )]
   1247 #[test]
   1248 fn power_set() {
   1249     #[cfg(target_pointer_width = "16")]
   1250     let feat_len_one_too_large = 17;
   1251     #[cfg(target_pointer_width = "32")]
   1252     let feat_len_one_too_large = 33;
   1253     #[cfg(target_pointer_width = "64")]
   1254     let feat_len_one_too_large = 65;
   1255     let mut feats = Features(vec![(String::new(), Vec::new()); feat_len_one_too_large]);
   1256     assert_eq!(PowerSet::new(&feats, false), Err(TooManyFeaturesErr));
   1257     #[cfg(target_pointer_width = "16")]
   1258     let max_feat_len = 16;
   1259     #[cfg(target_pointer_width = "32")]
   1260     let max_feat_len = 32;
   1261     #[cfg(target_pointer_width = "64")]
   1262     let max_feat_len = 64;
   1263     feats.0 = vec![(String::new(), Vec::new()); max_feat_len];
   1264     #[cfg(any(
   1265         target_pointer_width = "16",
   1266         target_pointer_width = "32",
   1267         target_pointer_width = "64"
   1268     ))]
   1269     assert_eq!(
   1270         PowerSet::new(&feats, false),
   1271         Ok(Some(PowerSet {
   1272             feats: feats.0.as_slice(),
   1273             has_remaining: true,
   1274             check_overlap: false,
   1275             idx: usize::MAX,
   1276             buffer: vec![""; max_feat_len],
   1277             set: String::new(),
   1278             skipped_sets_counter: 0,
   1279             skip_empty_set: false,
   1280         }))
   1281     );
   1282     feats.0 = Vec::new();
   1283     assert_eq!(
   1284         PowerSet::new(&feats, false),
   1285         Ok(Some(PowerSet {
   1286             feats: feats.0.as_slice(),
   1287             has_remaining: true,
   1288             check_overlap: false,
   1289             idx: 0,
   1290             buffer: Vec::new(),
   1291             set: String::new(),
   1292             skipped_sets_counter: 0,
   1293             skip_empty_set: false,
   1294         }))
   1295     );
   1296     assert_eq!(PowerSet::new(&feats, true), Ok(None));
   1297     let mut power_set = PowerSet::new(&feats, false)
   1298         .unwrap_or_else(|_e| {
   1299             unreachable!("not possible since we just verified PowerSet::new returned Ok")
   1300         })
   1301         .unwrap_or_else(|| {
   1302             unreachable!("not possible since we just verified PowerSet::new returned Ok(Some)")
   1303         });
   1304     assert_eq!(power_set.len(), NonZeroUsizePlus1::new(1));
   1305     assert_eq!(power_set.next_set(), Some(""));
   1306     assert_eq!(
   1307         power_set,
   1308         PowerSet {
   1309             feats: feats.0.as_slice(),
   1310             has_remaining: false,
   1311             check_overlap: false,
   1312             idx: 0,
   1313             buffer: Vec::new(),
   1314             set: String::new(),
   1315             skipped_sets_counter: 0,
   1316             skip_empty_set: false
   1317         }
   1318     );
   1319     assert_eq!(power_set.next_set(), None);
   1320     assert_eq!(power_set.len(), NonZeroUsizePlus1::new(1));
   1321     assert_eq!(
   1322         power_set,
   1323         PowerSet {
   1324             feats: feats.0.as_slice(),
   1325             has_remaining: false,
   1326             check_overlap: false,
   1327             idx: 0,
   1328             buffer: Vec::new(),
   1329             set: String::new(),
   1330             skipped_sets_counter: 0,
   1331             skip_empty_set: false
   1332         }
   1333     );
   1334     assert_eq!(power_set.next_set(), None);
   1335     power_set.reset();
   1336     assert_eq!(
   1337         power_set,
   1338         PowerSet {
   1339             feats: feats.0.as_slice(),
   1340             has_remaining: true,
   1341             check_overlap: false,
   1342             idx: 0,
   1343             buffer: Vec::new(),
   1344             set: String::new(),
   1345             skipped_sets_counter: 0,
   1346             skip_empty_set: false
   1347         }
   1348     );
   1349     assert_eq!(power_set.next_set(), Some(""));
   1350     assert_eq!(
   1351         power_set,
   1352         PowerSet {
   1353             feats: feats.0.as_slice(),
   1354             has_remaining: false,
   1355             check_overlap: false,
   1356             idx: 0,
   1357             buffer: Vec::new(),
   1358             set: String::new(),
   1359             skipped_sets_counter: 0,
   1360             skip_empty_set: false
   1361         }
   1362     );
   1363     assert_eq!(power_set.next_set(), None);
   1364     assert_eq!(
   1365         power_set,
   1366         PowerSet {
   1367             feats: feats.0.as_slice(),
   1368             has_remaining: false,
   1369             check_overlap: false,
   1370             idx: 0,
   1371             buffer: Vec::new(),
   1372             set: String::new(),
   1373             skipped_sets_counter: 0,
   1374             skip_empty_set: false
   1375         }
   1376     );
   1377     assert_eq!(power_set.next_set(), None);
   1378     // [features]
   1379     // a = ["b"]
   1380     // b = ["c", "d"]
   1381     // c = []
   1382     // d = []
   1383     feats.0 = vec![
   1384         ("a".to_owned(), vec!["b".to_owned()]),
   1385         ("b".to_owned(), vec!["c".to_owned(), "d".to_owned()]),
   1386         ("c".to_owned(), Vec::new()),
   1387         ("d".to_owned(), Vec::new()),
   1388     ];
   1389     assert_eq!(
   1390         PowerSet::new(&feats, false),
   1391         Ok(Some(PowerSet {
   1392             feats: feats.0.as_slice(),
   1393             has_remaining: true,
   1394             // At least one feature depends on another, so this will be set to `true`.
   1395             check_overlap: true,
   1396             idx: 15,
   1397             buffer: vec!["a", "b", "c", "d"],
   1398             set: String::new(),
   1399             skipped_sets_counter: 0,
   1400             skip_empty_set: false
   1401         }))
   1402     );
   1403     power_set = PowerSet::new(&feats, false)
   1404         .unwrap_or_else(|_e| {
   1405             unreachable!("not possible since we just verified PowerSet::new returned Ok")
   1406         })
   1407         .unwrap_or_else(|| {
   1408             unreachable!("not possible since we just verified PowerSet::new returned Ok(Some)")
   1409         });
   1410     assert_eq!(power_set.len(), NonZeroUsizePlus1::new(16));
   1411     // Order is the following:
   1412     // 1. a,b,c,d: skipped since a depends on b.
   1413     // 2. b,c,d: skipped since b depends on c.
   1414     // 3. a,c,d: skipped since a depends on c (via b).
   1415     // 4. c,d
   1416     // 5. a,b,d: skipped since a depends on b.
   1417     // 6. b,d: skipped since b depends on d.
   1418     // 7. a,d: skipped since a depends on d (via b).
   1419     // 8. d
   1420     // 9. a,b,c: skipped since a depends on b.
   1421     // 10. b,c: skipped since b depends on c.
   1422     // 11. a,c: skipped since a depends on c (via b).
   1423     // 12. c
   1424     // 13. a,b: skipped since a depends on b.
   1425     // 14. b
   1426     // 15. a
   1427     // 16.
   1428     assert_eq!(power_set.next_set(), Some("c,d"));
   1429     assert_eq!(
   1430         power_set,
   1431         PowerSet {
   1432             feats: feats.0.as_slice(),
   1433             has_remaining: true,
   1434             check_overlap: true,
   1435             // We started at 15, and we iterated 4 items (skipping 3).
   1436             idx: 11,
   1437             buffer: vec!["c", "d"],
   1438             set: "c,d".to_owned(),
   1439             skipped_sets_counter: 3,
   1440             skip_empty_set: false
   1441         }
   1442     );
   1443     assert_eq!(power_set.next_set(), Some("d"));
   1444     assert_eq!(
   1445         power_set,
   1446         PowerSet {
   1447             feats: feats.0.as_slice(),
   1448             has_remaining: true,
   1449             check_overlap: true,
   1450             // We started at 11, and we iterated 4 items (skipping 3).
   1451             idx: 7,
   1452             buffer: vec!["d"],
   1453             set: "d".to_owned(),
   1454             skipped_sets_counter: 6,
   1455             skip_empty_set: false
   1456         }
   1457     );
   1458     assert_eq!(power_set.next_set(), Some("c"));
   1459     assert_eq!(
   1460         power_set,
   1461         PowerSet {
   1462             feats: feats.0.as_slice(),
   1463             has_remaining: true,
   1464             check_overlap: true,
   1465             // We started at 7, and we iterated 4 items (skipping 3).
   1466             idx: 3,
   1467             buffer: vec!["c"],
   1468             set: "c".to_owned(),
   1469             skipped_sets_counter: 9,
   1470             skip_empty_set: false
   1471         }
   1472     );
   1473     assert_eq!(power_set.next_set(), Some("b"));
   1474     assert_eq!(
   1475         power_set,
   1476         PowerSet {
   1477             feats: feats.0.as_slice(),
   1478             has_remaining: true,
   1479             check_overlap: true,
   1480             // We started at 3, and we iterated 2 items (skipping 1).
   1481             idx: 1,
   1482             buffer: vec!["b"],
   1483             set: "b".to_owned(),
   1484             skipped_sets_counter: 10,
   1485             skip_empty_set: false
   1486         }
   1487     );
   1488     assert_eq!(power_set.next_set(), Some("a"));
   1489     assert_eq!(
   1490         power_set,
   1491         PowerSet {
   1492             feats: feats.0.as_slice(),
   1493             has_remaining: true,
   1494             check_overlap: true,
   1495             // We started at 1, and we iterated 1 item.
   1496             idx: 0,
   1497             buffer: vec!["a"],
   1498             set: "a".to_owned(),
   1499             skipped_sets_counter: 10,
   1500             skip_empty_set: false
   1501         }
   1502     );
   1503     assert_eq!(power_set.next_set(), Some(""));
   1504     assert_eq!(
   1505         power_set,
   1506         PowerSet {
   1507             feats: feats.0.as_slice(),
   1508             has_remaining: false,
   1509             check_overlap: true,
   1510             // We started at 0, and we iterated 1 item but we don't underflow instead `has_remaining` is set
   1511             // to `false`.
   1512             idx: 0,
   1513             buffer: Vec::new(),
   1514             set: String::new(),
   1515             skipped_sets_counter: 10,
   1516             skip_empty_set: false
   1517         }
   1518     );
   1519     assert_eq!(power_set.next_set(), None);
   1520     // Internal state is left unchanged.
   1521     assert_eq!(
   1522         power_set,
   1523         PowerSet {
   1524             feats: feats.0.as_slice(),
   1525             has_remaining: false,
   1526             check_overlap: true,
   1527             idx: 0,
   1528             buffer: Vec::new(),
   1529             set: String::new(),
   1530             skipped_sets_counter: 10,
   1531             skip_empty_set: false
   1532         }
   1533     );
   1534     assert_eq!(power_set.next_set(), None);
   1535     // Internal state is left unchanged.
   1536     assert_eq!(
   1537         power_set,
   1538         PowerSet {
   1539             feats: feats.0.as_slice(),
   1540             has_remaining: false,
   1541             check_overlap: true,
   1542             idx: 0,
   1543             buffer: Vec::new(),
   1544             set: String::new(),
   1545             skipped_sets_counter: 10,
   1546             skip_empty_set: false
   1547         }
   1548     );
   1549     assert_eq!(power_set.len(), NonZeroUsizePlus1::new(16));
   1550     power_set.reset();
   1551     // `PowerSet::reset` only resets what is necessary nothing more; in particular, `buffer` and `set` are
   1552     // left alone.
   1553     assert_eq!(
   1554         power_set,
   1555         PowerSet {
   1556             feats: feats.0.as_slice(),
   1557             has_remaining: true,
   1558             check_overlap: true,
   1559             idx: 15,
   1560             buffer: Vec::new(),
   1561             set: String::new(),
   1562             skipped_sets_counter: 0,
   1563             skip_empty_set: false
   1564         }
   1565     );
   1566     assert_eq!(power_set.len(), NonZeroUsizePlus1::new(16));
   1567     // Same as above except no feature depends on any other.
   1568     // [features]
   1569     // a = []
   1570     // b = []
   1571     // c = []
   1572     // d = []
   1573     feats.0 = vec![
   1574         ("a".to_owned(), Vec::new()),
   1575         ("b".to_owned(), Vec::new()),
   1576         ("c".to_owned(), Vec::new()),
   1577         ("d".to_owned(), Vec::new()),
   1578     ];
   1579     assert_eq!(
   1580         PowerSet::new(&feats, false),
   1581         Ok(Some(PowerSet {
   1582             feats: feats.0.as_slice(),
   1583             has_remaining: true,
   1584             check_overlap: false,
   1585             idx: 15,
   1586             buffer: vec!["a", "b", "c", "d"],
   1587             set: String::new(),
   1588             skipped_sets_counter: 0,
   1589             skip_empty_set: false
   1590         }))
   1591     );
   1592     power_set = PowerSet::new(&feats, false)
   1593         .unwrap_or_else(|_e| {
   1594             unreachable!("not possible since we just verified PowerSet::new returned Ok")
   1595         })
   1596         .unwrap_or_else(|| {
   1597             unreachable!("not possible since we just verified PowerSet::new returned Ok(Some)")
   1598         });
   1599     assert_eq!(power_set.len(), NonZeroUsizePlus1::new(16));
   1600     // Order is the same as above except nothing is skipped:
   1601     // 1. a,b,c,d
   1602     // 2. b,c,d
   1603     // 3. a,c,d
   1604     // 4. c,d
   1605     // 5. a,b,d
   1606     // 6. b,d
   1607     // 7. a,d
   1608     // 8. d
   1609     // 9. a,b,c
   1610     // 10. b,c
   1611     // 11. a,c
   1612     // 12. c
   1613     // 13. a,b
   1614     // 14. b
   1615     // 15. a
   1616     // 16.
   1617     assert_eq!(power_set.next_set(), Some("a,b,c,d"));
   1618     assert_eq!(
   1619         power_set,
   1620         PowerSet {
   1621             feats: feats.0.as_slice(),
   1622             has_remaining: true,
   1623             check_overlap: false,
   1624             idx: 14,
   1625             buffer: vec!["a", "b", "c", "d"],
   1626             set: "a,b,c,d".to_owned(),
   1627             skipped_sets_counter: 0,
   1628             skip_empty_set: false
   1629         }
   1630     );
   1631     assert_eq!(power_set.next_set(), Some("b,c,d"));
   1632     assert_eq!(
   1633         power_set,
   1634         PowerSet {
   1635             feats: feats.0.as_slice(),
   1636             has_remaining: true,
   1637             check_overlap: false,
   1638             idx: 13,
   1639             buffer: vec!["b", "c", "d"],
   1640             set: "b,c,d".to_owned(),
   1641             skipped_sets_counter: 0,
   1642             skip_empty_set: false
   1643         }
   1644     );
   1645     assert_eq!(power_set.next_set(), Some("a,c,d"));
   1646     assert_eq!(
   1647         power_set,
   1648         PowerSet {
   1649             feats: feats.0.as_slice(),
   1650             has_remaining: true,
   1651             check_overlap: false,
   1652             idx: 12,
   1653             buffer: vec!["a", "c", "d"],
   1654             set: "a,c,d".to_owned(),
   1655             skipped_sets_counter: 0,
   1656             skip_empty_set: false
   1657         }
   1658     );
   1659     assert_eq!(power_set.next_set(), Some("c,d"));
   1660     assert_eq!(
   1661         power_set,
   1662         PowerSet {
   1663             feats: feats.0.as_slice(),
   1664             has_remaining: true,
   1665             check_overlap: false,
   1666             idx: 11,
   1667             buffer: vec!["c", "d"],
   1668             set: "c,d".to_owned(),
   1669             skipped_sets_counter: 0,
   1670             skip_empty_set: false
   1671         }
   1672     );
   1673     assert_eq!(power_set.next_set(), Some("a,b,d"));
   1674     assert_eq!(
   1675         power_set,
   1676         PowerSet {
   1677             feats: feats.0.as_slice(),
   1678             has_remaining: true,
   1679             check_overlap: false,
   1680             idx: 10,
   1681             buffer: vec!["a", "b", "d"],
   1682             set: "a,b,d".to_owned(),
   1683             skipped_sets_counter: 0,
   1684             skip_empty_set: false
   1685         }
   1686     );
   1687     assert_eq!(power_set.next_set(), Some("b,d"));
   1688     assert_eq!(
   1689         power_set,
   1690         PowerSet {
   1691             feats: feats.0.as_slice(),
   1692             has_remaining: true,
   1693             check_overlap: false,
   1694             idx: 9,
   1695             buffer: vec!["b", "d"],
   1696             set: "b,d".to_owned(),
   1697             skipped_sets_counter: 0,
   1698             skip_empty_set: false
   1699         }
   1700     );
   1701     assert_eq!(power_set.next_set(), Some("a,d"));
   1702     assert_eq!(
   1703         power_set,
   1704         PowerSet {
   1705             feats: feats.0.as_slice(),
   1706             has_remaining: true,
   1707             check_overlap: false,
   1708             idx: 8,
   1709             buffer: vec!["a", "d"],
   1710             set: "a,d".to_owned(),
   1711             skipped_sets_counter: 0,
   1712             skip_empty_set: false
   1713         }
   1714     );
   1715     assert_eq!(power_set.next_set(), Some("d"));
   1716     assert_eq!(
   1717         power_set,
   1718         PowerSet {
   1719             feats: feats.0.as_slice(),
   1720             has_remaining: true,
   1721             check_overlap: false,
   1722             idx: 7,
   1723             buffer: vec!["d"],
   1724             set: "d".to_owned(),
   1725             skipped_sets_counter: 0,
   1726             skip_empty_set: false
   1727         }
   1728     );
   1729     assert_eq!(power_set.next_set(), Some("a,b,c"));
   1730     assert_eq!(
   1731         power_set,
   1732         PowerSet {
   1733             feats: feats.0.as_slice(),
   1734             has_remaining: true,
   1735             check_overlap: false,
   1736             idx: 6,
   1737             buffer: vec!["a", "b", "c"],
   1738             set: "a,b,c".to_owned(),
   1739             skipped_sets_counter: 0,
   1740             skip_empty_set: false
   1741         }
   1742     );
   1743     assert_eq!(power_set.next_set(), Some("b,c"));
   1744     assert_eq!(
   1745         power_set,
   1746         PowerSet {
   1747             feats: feats.0.as_slice(),
   1748             has_remaining: true,
   1749             check_overlap: false,
   1750             idx: 5,
   1751             buffer: vec!["b", "c"],
   1752             set: "b,c".to_owned(),
   1753             skipped_sets_counter: 0,
   1754             skip_empty_set: false
   1755         }
   1756     );
   1757     assert_eq!(power_set.next_set(), Some("a,c"));
   1758     assert_eq!(
   1759         power_set,
   1760         PowerSet {
   1761             feats: feats.0.as_slice(),
   1762             has_remaining: true,
   1763             check_overlap: false,
   1764             idx: 4,
   1765             buffer: vec!["a", "c"],
   1766             set: "a,c".to_owned(),
   1767             skipped_sets_counter: 0,
   1768             skip_empty_set: false
   1769         }
   1770     );
   1771     assert_eq!(power_set.next_set(), Some("c"));
   1772     assert_eq!(
   1773         power_set,
   1774         PowerSet {
   1775             feats: feats.0.as_slice(),
   1776             has_remaining: true,
   1777             check_overlap: false,
   1778             idx: 3,
   1779             buffer: vec!["c"],
   1780             set: "c".to_owned(),
   1781             skipped_sets_counter: 0,
   1782             skip_empty_set: false
   1783         }
   1784     );
   1785     assert_eq!(power_set.next_set(), Some("a,b"));
   1786     assert_eq!(
   1787         power_set,
   1788         PowerSet {
   1789             feats: feats.0.as_slice(),
   1790             has_remaining: true,
   1791             check_overlap: false,
   1792             idx: 2,
   1793             buffer: vec!["a", "b"],
   1794             set: "a,b".to_owned(),
   1795             skipped_sets_counter: 0,
   1796             skip_empty_set: false
   1797         }
   1798     );
   1799     assert_eq!(power_set.next_set(), Some("b"));
   1800     assert_eq!(
   1801         power_set,
   1802         PowerSet {
   1803             feats: feats.0.as_slice(),
   1804             has_remaining: true,
   1805             check_overlap: false,
   1806             idx: 1,
   1807             buffer: vec!["b"],
   1808             set: "b".to_owned(),
   1809             skipped_sets_counter: 0,
   1810             skip_empty_set: false
   1811         }
   1812     );
   1813     assert_eq!(power_set.next_set(), Some("a"));
   1814     assert_eq!(
   1815         power_set,
   1816         PowerSet {
   1817             feats: feats.0.as_slice(),
   1818             has_remaining: true,
   1819             check_overlap: false,
   1820             idx: 0,
   1821             buffer: vec!["a"],
   1822             set: "a".to_owned(),
   1823             skipped_sets_counter: 0,
   1824             skip_empty_set: false
   1825         }
   1826     );
   1827     assert_eq!(power_set.next_set(), Some(""));
   1828     assert_eq!(
   1829         power_set,
   1830         PowerSet {
   1831             feats: feats.0.as_slice(),
   1832             has_remaining: false,
   1833             check_overlap: false,
   1834             idx: 0,
   1835             buffer: Vec::new(),
   1836             set: String::new(),
   1837             skipped_sets_counter: 0,
   1838             skip_empty_set: false
   1839         }
   1840     );
   1841     assert_eq!(power_set.next_set(), None);
   1842     assert_eq!(
   1843         power_set,
   1844         PowerSet {
   1845             feats: feats.0.as_slice(),
   1846             has_remaining: false,
   1847             check_overlap: false,
   1848             idx: 0,
   1849             buffer: Vec::new(),
   1850             set: String::new(),
   1851             skipped_sets_counter: 0,
   1852             skip_empty_set: false
   1853         }
   1854     );
   1855     assert_eq!(power_set.len(), NonZeroUsizePlus1::new(16));
   1856     feats.0 = vec![("a".to_owned(), Vec::new())];
   1857     assert_eq!(
   1858         PowerSet::new(&feats, true),
   1859         Ok(Some(PowerSet {
   1860             feats: feats.0.as_slice(),
   1861             has_remaining: true,
   1862             check_overlap: false,
   1863             idx: 1,
   1864             buffer: vec!["a"],
   1865             set: String::new(),
   1866             skipped_sets_counter: 0,
   1867             skip_empty_set: true
   1868         }))
   1869     );
   1870     power_set = PowerSet::new(&feats, true)
   1871         .unwrap_or_else(|_e| {
   1872             unreachable!("not possible since we just verified PowerSet::new returned Ok")
   1873         })
   1874         .unwrap_or_else(|| {
   1875             unreachable!("not possible since we just verified PowerSet::new returned Ok(Some)")
   1876         });
   1877     assert_eq!(power_set.len(), NonZeroUsizePlus1::new(1));
   1878     assert_eq!(power_set.next_set(), Some("a"));
   1879     assert_eq!(
   1880         power_set,
   1881         PowerSet {
   1882             feats: feats.0.as_slice(),
   1883             has_remaining: false,
   1884             check_overlap: false,
   1885             idx: 0,
   1886             buffer: vec!["a"],
   1887             set: "a".to_owned(),
   1888             skipped_sets_counter: 0,
   1889             skip_empty_set: true,
   1890         }
   1891     );
   1892     assert_eq!(power_set.next_set(), None);
   1893     assert_eq!(
   1894         power_set,
   1895         PowerSet {
   1896             feats: feats.0.as_slice(),
   1897             has_remaining: false,
   1898             check_overlap: false,
   1899             idx: 0,
   1900             buffer: vec!["a"],
   1901             set: "a".to_owned(),
   1902             skipped_sets_counter: 0,
   1903             skip_empty_set: true,
   1904         }
   1905     );
   1906     assert_eq!(power_set.next_set(), None);
   1907     assert_eq!(
   1908         power_set,
   1909         PowerSet {
   1910             feats: feats.0.as_slice(),
   1911             has_remaining: false,
   1912             check_overlap: false,
   1913             idx: 0,
   1914             buffer: vec!["a"],
   1915             set: "a".to_owned(),
   1916             skipped_sets_counter: 0,
   1917             skip_empty_set: true,
   1918         }
   1919     );
   1920     power_set.reset();
   1921     assert_eq!(
   1922         power_set,
   1923         PowerSet {
   1924             feats: feats.0.as_slice(),
   1925             has_remaining: true,
   1926             check_overlap: false,
   1927             idx: 1,
   1928             buffer: vec!["a"],
   1929             set: "a".to_owned(),
   1930             skipped_sets_counter: 0,
   1931             skip_empty_set: true,
   1932         }
   1933     );
   1934     assert_eq!(power_set.next_set(), Some("a"));
   1935     assert_eq!(power_set.next_set(), None);
   1936     assert_eq!(
   1937         power_set,
   1938         PowerSet {
   1939             feats: feats.0.as_slice(),
   1940             has_remaining: false,
   1941             check_overlap: false,
   1942             idx: 0,
   1943             buffer: vec!["a"],
   1944             set: "a".to_owned(),
   1945             skipped_sets_counter: 0,
   1946             skip_empty_set: true,
   1947         }
   1948     );
   1949     assert_eq!(power_set.len(), NonZeroUsizePlus1::new(1));
   1950 }