Skip to content

Using<TCollectionType, TMemberType> is unclear #4726

@RenderMichael

Description

@RenderMichael

Excuse the example, it's a little contrived, it's as minimal a repro as I could think of.

I am working with ZIP archives, and I want to make sure a entry I am getting (which comes from another archive) is contained in my reference archive. My custom comparer is failing, though:

using NUnit.Framework.Constraints;

using System.Collections.ObjectModel;
using System.IO.Compression;

namespace NUnitRepro2;

public class Tests
{
    [Test] // fails
    public void ZipArchiveContainsTest()
    {
        using var archiveContents = new MemoryStream();
        using ZipArchive archive = ConstantArchive(archiveContents);
        using var archiveContents2 = new MemoryStream();
        using ZipArchive otherArchive = ConstantArchive(archiveContents2);

        ZipArchiveEntry entry = otherArchive.Entries[0];
        Assert.That(archive.Entries, Does.Contain(entry)
            .Using<ReadOnlyCollection<ZipArchiveEntry>, ZipArchiveEntry>((collection, needle) =>
            {
                foreach (var actualEntry in collection)
                {
                    using var leftValue = actualEntry.Open();
                    using var rightValue = needle.Open();

                    var comparison = new EqualConstraint(leftValue).ApplyTo(rightValue);
                    return comparison.Status is ConstraintStatus.Success;
                }

                return false;
            }));
    }

    [Test] // success!
    public void ZipArchiveWorkaroundTest()
    {
        using var archiveContents = new MemoryStream();
        using ZipArchive archive = ConstantArchive(archiveContents);
        using var archiveContents2 = new MemoryStream();
        using ZipArchive otherArchive = ConstantArchive(archiveContents2);

        ZipArchiveEntry entry = otherArchive.Entries[0];

        ZipArchive entryWrapper = MakeNewArchiveAroundEntry(entry);
        Assert.That(archive.Entries, Is.EqualTo(entryWrapper.Entries).Using<ZipArchiveEntry>((left, right) =>
        {
            using var leftValue = left.Open();
            using var rightValue = right.Open();

            var comparison = new EqualConstraint(leftValue).ApplyTo(rightValue);
            return comparison.Status is ConstraintStatus.Success;
        }));
    }

    private static ZipArchive MakeNewArchiveAroundEntry(ZipArchiveEntry entry)
    {
        var archiveContents = new MemoryStream();

        using (var archive = new ZipArchive(archiveContents, ZipArchiveMode.Create, leaveOpen: true))
        {
            ZipArchiveEntry demoFile = archive.CreateEntry(entry.Name);

            using Stream entryStream = demoFile.Open();
            using Stream entryContents = entry.Open();
            entryContents.CopyTo(entryStream);
        }

        return new ZipArchive(archiveContents, ZipArchiveMode.Read, leaveOpen: false);
    }

    private static ZipArchive ConstantArchive(MemoryStream archiveContents)
    {
        const string fileContentString = "Hello!";

        using (var archive = new ZipArchive(archiveContents, ZipArchiveMode.Create, leaveOpen: true))
        {
            ZipArchiveEntry demoFile = archive.CreateEntry("Hello entry");

            using Stream entryStream = demoFile.Open();

            using var entryFs = new StreamWriter(entryStream);
            entryFs.Write(fileContentString);
        }

        return new ZipArchive(archiveContents, ZipArchiveMode.Read, leaveOpen: false);
    }
}

As you can see, my workaround has been to make a new archive around the entry, and use a custom comparer there. However, there's still an underlying issue with SomeItemsConstraint.Using<TCollectionType, TMemberType> which doesn't exist with EqualConstraint.Using<T>.

Unless I am doing something wrong here and there's no bug, I am happy to try and fix this myself.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions