casey/intermodal

Would we possible to release a library crate to use it as a package?

josecelano opened this issue · 1 comments

Hi. First of all, thank you for this fantastic application! I'm working on some BitTorrent projects, and this application has been very useful for us.

I'm using the application mainly to generate random torrent files for testing. I'm contributing to a BitTorrent Tracker and Index written in Rust. The Index Backend is a REST API written in Rust.

In the API, we have some tests, such as an E2E test to upload a new torrent file (with the metadata) to the index. I want to avoid using the same fixtures (pre-built torrent files), so I'm generating a new torrent file on-the-fly every time the test is executed. You can see a sample test here.

I wrote a small function which is a wrapper for the intermodal tool. At that time, I was already wondering if it could be possible to use the imdl command as a package (not a binary). I did not want to introduce a system dependency for running the tests. For now, I'm doing so, and you need to install imdl to run our unit tests.

Now I'm working on adding tests to the Index Frontend application, and I have the same problem again. I'm using Cypress, and I want to generate random torrent files. I've been working on this PR, and one of the solutions we are considering is to add an extra development endpoint that we can use to create "test" torrent files. I want to use imdl command, but I would prefer to use this repo functionality as a cargo dependency.

@da2ce7 and I have discussed implementing a proper solution to generate random test torrent files. We think that:

  • A well-implemented package for generating test/mock torrents would be very beneficial for the community that is building BitTorrent applications.
  • The package could be this repo. It could be a lib/binary repo.

One of the problems I see is the difficulty of creating torrents without using the file system. As seen in this repo's tests, you create temp dirs for the contents. That's the same approach we have used in our projects. Ideally, we should be able to get the torrent file binary contests without using the filesystem or mocking the filesystem.

I think a potential package could look similar to what you are doing in your tests. For example:

  #[test]
  fn create_from_stdin() {
    let mut env = test_env! {
      args: [
        "torrent",
        "create",
        "--input",
        "-",
        "--announce",
        "http://bar",
        "--name",
        "foo",
        "--output",
        "foo.torrent",
        "--md5",
      ],
      input: "hello",
      tree: {},
    };

    env.assert_ok();

    let metainfo = env.load_metainfo("foo.torrent");

    assert_eq!(metainfo.info.pieces, PieceList::from_pieces(["hello"]));

    assert_eq!(
      metainfo.info.mode,
      Mode::Single {
        length: Bytes(5),
        md5sum: Some(Md5Digest::from_data("hello")),
      }
    );
  }

Of course, we would not need to pass the command line arguments but just the data structure:

pub(crate) struct CreateContent {
  pub(crate) files: Option<Files>,
  pub(crate) piece_length: Bytes,
  pub(crate) progress_bar: ProgressBar,
  pub(crate) name: String,
  pub(crate) output: OutputTarget,
}

That would be the simplest way to expose the library, but it requires you to use the filesystem anyway. For single-file torrents, we could use a different interface and do something similar to what you do when you get the contents from the standard input.

Mocking the filesystem could imply more changes, for example, a trait for a kind of in-memory filesystem so that you do not need to create the files on disk.

Does it make sense for you?

Links

Example test: https://github.com/torrust/torrust-index-backend/blob/develop/tests/e2e/web/api/v1/contexts/torrent/contract.rs#L306-L333

Function to create torrent files using imdl: https://github.com/torrust/torrust-index-backend/blob/develop/tests/common/contexts/torrent/file.rs#L32-L52