bin: lib: script: Expose cros_generate_dlc_artifacts

.. to allow for CrOS DLC developers/clients to start invoking and
generating DLC artifacts.

Produced artifacts:
```
[4.0K]  dlcart
├── [4.0M]  dlc.img
└── [ 659]  meta.tar.zst
[4.0K]  dlcartmeta
└── [ 281]  metadata
```

Inside basic mount:
```
[         42]  mnt/
├── [       1472]  LICENSE
└── [         27]  root
    └── [    4194304]  file
```

Replace below <..> variables with specific DLC values.
[..] are optional.
Tests:
```
Official upload using --upload:
$> cros_sdk -- \
  cros_generate_dlc_artifacts \
  --src-dir <SOURCE_DIR> \
  --license ../third_party/chromiumos-overlay/licenses/<LICENSE> \
  --id <DLC_ID> \
  --preallocated-blocks <PREALLOCATED_BLOCKS>\
  --version <VERSION> \
  [--output-dir <DLC_OUTPUT_DIR>/] \
  [--output-metadata_dir <DLC_OUTPUT_METADATA_DIR>/] \
  [--debug] \
  [--upload] \
  [--upload-dry-run] \
  [--uri-path <URI_DIR>] \
  [--disable-randomness]

* Dry run upload using --upload-dry-run
* Enable randomness by not using --disable-randomness
* Output artifacts and/or metadata using --output-* options
* Override URI output using --uri-path
```

BUG=b:286327155
TEST=comment above
TEST=./run_tests

Change-Id: I703d8988983b84202f352ce0367115f9ffe1cbf1
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/chromite/+/4707265
Commit-Queue: Jae Hoon Kim <kimjae@chromium.org>
Reviewed-by: Yuanpeng Ni‎ <yuanpengni@chromium.org>
Reviewed-by: Mike Frysinger <vapier@chromium.org>
Auto-Submit: Jae Hoon Kim <kimjae@chromium.org>
Tested-by: Jae Hoon Kim <kimjae@chromium.org>
diff --git a/scripts/cros_generate_dlc_artifacts_unittest.py b/scripts/cros_generate_dlc_artifacts_unittest.py
new file mode 100644
index 0000000..c1d0f58
--- /dev/null
+++ b/scripts/cros_generate_dlc_artifacts_unittest.py
@@ -0,0 +1,75 @@
+# Copyright 2023 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Unit tests for cros_generate_dlc_artifacts."""
+
+
+from unittest import mock
+
+import pytest
+
+from chromite.lib import dlc_lib
+from chromite.scripts import cros_generate_dlc_artifacts
+
+
+@pytest.mark.parametrize("dry_run", ((False), (True)))
+def test_upload_dlc_artifacts(dry_run):
+    """Tests out UploadDlcArtifacts with dry_run option"""
+    artifact_mock = mock.Mock()
+    cros_generate_dlc_artifacts.UploadDlcArtifacts(
+        artifact_mock, dry_run=dry_run
+    )
+    artifact_mock.Upload.assert_called_with(dry_run=dry_run)
+
+
+@pytest.mark.parametrize("dlc_id", ("some-dlc-id",))
+@pytest.mark.parametrize("preallocated_blocks", (123,))
+@pytest.mark.parametrize("name", ((""), ("<some-name>")))
+@pytest.mark.parametrize("description", ((""), ("<some-description>")))
+@pytest.mark.parametrize("version", ("<some-version>",))
+@mock.patch.object(dlc_lib, "EbuildParams")
+def test_generate_dlc_params(
+    mock_ebuild_params,
+    dlc_id,
+    preallocated_blocks,
+    name,
+    description,
+    version,
+    tmp_path,
+):
+    """Tests out GenerateDlcParams"""
+    tmpfile = tmp_path / "license"
+    tmpfile.touch()
+    argv = [
+        "--src-dir",
+        ".",
+        "--license",
+        str(tmpfile),
+        *(["--id", f"{dlc_id}"] if dlc_id else []),
+        *(
+            ["--preallocated-blocks", f"{preallocated_blocks}"]
+            if preallocated_blocks
+            else []
+        ),
+        *(["--name", f"{name}"] if name else []),
+        *(["--description", f"{description}"] if description else []),
+        *(["--version", f"{version}"] if version else []),
+    ]
+    opts = cros_generate_dlc_artifacts.ParseArguments(argv)
+    cros_generate_dlc_artifacts.GenerateDlcParams(opts)
+    mock_ebuild_params.assert_called_with(
+        dlc_id=dlc_id,
+        dlc_package="package",
+        fs_type=dlc_lib.SQUASHFS_TYPE,
+        pre_allocated_blocks=preallocated_blocks,
+        version=version,
+        name=name,
+        description=description,
+        preload=False,
+        used_by="",
+        mount_file_required=False,
+        fullnamerev="",
+        scaled=True,
+        loadpin_verity_digest=False,
+    )