在Elixir中断言zip存档内容的最佳方法是什么?

Low*_*ong 5 erlang zip elixir zipfile

目前我在做什么:

  1. 通过让它压缩文件/目录来测试功能.断言它存在.
  2. 使用:zip.t:zip.tt让它列出zip文件夹的内容,看看它是否是我所期待的.

不知怎的,我想我错过了一些东西.测试更好:zip.table吗?该功能看起来令人困惑.有人可以举例说明如何使用它吗?下面是我得到的输出示例,但我无法弄清楚如何将其变成测试?对于zip档案来说,md5sum是一个更好的测试吗?

iex(4)> :zip.table('testing.zip')
{:ok,
 [{:zip_comment, []},
  {:zip_file, 'mix.exs',
   {:file_info, 930, :regular, :read_write, {{2015, 7, 15}, {2, 11, 9}},
    {{2015, 7, 15}, {2, 11, 9}}, {{2015, 7, 15}, {2, 11, 9}}, 54, 1, 0, 0, 0, 0,
    0}, [], 0, 444},
  {:zip_file, 'mix.lock',
   {:file_info, 332, :regular, :read_write, {{2015, 7, 15}, {2, 9, 6}},
    {{2015, 7, 15}, {2, 9, 6}}, {{2015, 7, 15}, {2, 9, 6}}, 54, 1, 0, 0, 0, 0,
    0}, [], 481, 152}]}
Run Code Online (Sandbox Code Playgroud)

Pat*_*ity 8

:zip来自Erlang 的模块并不是很容易使用,我会尝试为你分解它.

首先,我们需要zip_file从Erlang开始按顺序对记录进行适当的表示,以便能够正确使用它.否则,我们将不得不对元组进行匹配,其中包含许多元素,这些元素会不必要地混乱我们的代码.以下模块主要基于Elixir File.Stat实现,并允许我们使用简单的点表示法访问那些难以处理的元组中的值.

require Record

defmodule Zip.File do
  record = Record.extract(:zip_file, from_lib: "stdlib/include/zip.hrl")
  keys   = :lists.map(&elem(&1, 0), record)
  vals   = :lists.map(&{&1, [], nil}, keys)
  pairs  = :lists.zip(keys, vals)

  defstruct keys

  def to_record(%Zip.File{unquote_splicing(pairs)}) do
    {:zip_file, unquote_splicing(vals)}
  end

  def from_record(zip_file)
  def from_record({:zip_file, unquote_splicing(vals)}) do
    %Zip.File{unquote_splicing(pairs)}
    |> Map.update!(:info, fn(info) -> File.Stat.from_record(info) end)
  end
end
Run Code Online (Sandbox Code Playgroud)

我们现在可以围绕Erlang zip模块构建一个小包装类.它没有包装所有方法,只包括我们将在这里使用的方法.我还添加了一个list_files/1只返回文件的函数,不包括列表中的目录和注释.

defmodule Zip do
  def open(archive) do
    {:ok, zip_handle} = :zip.zip_open(archive)
    zip_handle
  end

  def close(zip_handle) do
    :zip.zip_close(zip_handle)
  end

  def list_dir(zip_handle) do
    {:ok, result} = :zip.zip_list_dir(zip_handle)
    result
  end

  def list_files(zip_handle) do
    list_dir(zip_handle)
    |> Enum.drop(1)
    |> Enum.map(&Zip.File.from_record/1)
    |> Enum.filter(&(&1.info.type == :regular))
  end
end
Run Code Online (Sandbox Code Playgroud)

假设我们有以下zip存档进行测试:

cd /tmp
touch foo bar baz
zip archive.zip foo bar baz
Run Code Online (Sandbox Code Playgroud)

现在您可以在zip存档中声明文件名:

test "files are in zip" do
  zip = Zip.open('/tmp/archive.zip')
  files = Zip.list_files(zip) |> Enum.map(&(&1.name))
  Zip.close(zip)
  assert files == ['foo', 'bar', 'baz']
end
Run Code Online (Sandbox Code Playgroud)

我将在zip存档上留下进一步的操作和断言供您实现,并希望这可以帮助您入门.