blob: 8f7bc9097e6b7551e2c74a9bc0f6934a85edefa8 [file]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
import json
import atr.classify as classify
import atr.models.safe as safe
async def test_archive_defaults_to_source():
path = safe.RelPath("apache-widget-1.0.tar.gz")
assert (await classify.classify(path)) == classify.FileType.SOURCE
async def test_archive_tgz_defaults_to_source():
path = safe.RelPath("apache-widget-1.0.tgz")
assert (await classify.classify(path)) == classify.FileType.SOURCE
async def test_archive_zip_defaults_to_source():
path = safe.RelPath("apache-widget-1.0.zip")
assert (await classify.classify(path)) == classify.FileType.SOURCE
async def test_binary_matcher_classifies_as_binary(tmp_path):
path = safe.RelPath("maven-mvnd-1.0.4-windows-amd64.zip")
result = await classify.classify(path, base_path=safe.StatePath(tmp_path), binary_matcher=_matches_windows)
assert result == classify.FileType.BINARY
async def test_binary_matcher_does_not_override_source_matcher(tmp_path):
path = safe.RelPath("apache-widget-1.0.tar.gz")
result = await classify.classify(
path, base_path=safe.StatePath(tmp_path), source_matcher=_always_true, binary_matcher=_always_true
)
assert result == classify.FileType.SOURCE
async def test_binary_matcher_wins_over_stem_heuristic(tmp_path):
path = safe.RelPath("apache-widget-1.0-src.tar.gz")
result = await classify.classify(path, base_path=safe.StatePath(tmp_path), binary_matcher=_always_true)
assert result == classify.FileType.BINARY
async def test_binary_stem_heuristic():
path = safe.RelPath("apache-widget-1.0-binary.zip")
assert (await classify.classify(path)) == classify.FileType.BINARY
def test_counts_docs_only():
assert classify.classify_from_counts("", 0, 0, 1) == classify.FileType.DOCS
def test_counts_docs_with_binary():
assert classify.classify_from_counts("", 0, 1, 1) == classify.FileType.BINARY
def test_counts_docs_with_source():
assert classify.classify_from_counts("", 1, 0, 1) == classify.FileType.SOURCE
async def test_disallowed_files_detected():
path = safe.RelPath("desktop.ini")
assert (await classify.classify(path)) == classify.FileType.DISALLOWED
async def test_docs_stem_heuristic():
path = safe.RelPath("apache-widget-1.0-docs.tar.gz")
assert (await classify.classify(path)) == classify.FileType.DOCS
async def test_docs_stem_heuristic_javadoc():
path = safe.RelPath("apache-widget-1.0-javadoc.zip")
assert (await classify.classify(path)) == classify.FileType.DOCS
async def test_docs_stem_heuristic_site():
path = safe.RelPath("apache-widget-1.0-site.tar.gz")
assert (await classify.classify(path)) == classify.FileType.DOCS
async def test_jar_defaults_to_binary():
path = safe.RelPath("apache-widget-1.0.jar")
assert (await classify.classify(path)) == classify.FileType.BINARY
def test_matchers_from_policy_builds_both(tmp_path):
source_matcher, binary_matcher = classify.matchers_from_policy(["*-src.*"], ["*-bin.*"], safe.StatePath(tmp_path))
assert source_matcher is not None
assert binary_matcher is not None
def test_matchers_from_policy_empty(tmp_path):
source_matcher, binary_matcher = classify.matchers_from_policy([], [], safe.StatePath(tmp_path))
assert source_matcher is None
assert binary_matcher is None
async def test_metadata_suffix_detected():
path = safe.RelPath("apache-widget-1.0.tar.gz.sha512")
assert (await classify.classify(path)) == classify.FileType.METADATA
async def test_npm_content_marker_classifies_as_binary(tmp_path):
path = safe.RelPath("apache-widget-1.0.tgz")
cache_dir = _build_npm_pack_layout(tmp_path, name="apache-widget", version="1.0.0")
result = await classify.classify(path, archive_cache_dir=safe.StatePath(cache_dir))
assert result == classify.FileType.BINARY
async def test_npm_content_marker_ignored_when_layout_invalid(tmp_path):
path = safe.RelPath("apache-widget-1.0.tgz")
cache_dir = _build_npm_pack_layout(tmp_path, name="apache-widget", version="1.0.0")
(cache_dir / "extra").mkdir()
result = await classify.classify(path, archive_cache_dir=safe.StatePath(cache_dir))
assert result == classify.FileType.SOURCE
async def test_npm_content_marker_ignored_when_package_dir_is_symlink(tmp_path):
path = safe.RelPath("apache-widget-1.0.tgz")
cache_dir = tmp_path / "cache"
real_dir = cache_dir / "real_pkg"
real_dir.mkdir(parents=True)
(real_dir / "package.json").write_text(json.dumps({"name": "widget", "version": "1.0.0"}))
(cache_dir / "package").symlink_to(real_dir, target_is_directory=True)
result = await classify.classify(path, archive_cache_dir=safe.StatePath(cache_dir))
assert result == classify.FileType.SOURCE
async def test_npm_content_marker_ignored_when_package_json_is_symlink(tmp_path):
path = safe.RelPath("apache-widget-1.0.tgz")
cache_dir = _build_npm_pack_layout(tmp_path, name="apache-widget", version="1.0.0")
package_json = cache_dir / "package" / "package.json"
shadow = cache_dir / "package" / "metadata.json"
package_json.rename(shadow)
package_json.symlink_to(shadow)
result = await classify.classify(path, archive_cache_dir=safe.StatePath(cache_dir))
assert result == classify.FileType.SOURCE
async def test_npm_content_marker_ignored_when_package_json_malformed(tmp_path):
path = safe.RelPath("apache-widget-1.0.tgz")
cache_dir = tmp_path / "cache"
package_dir = cache_dir / "package"
package_dir.mkdir(parents=True)
(package_dir / "package.json").write_text("{ not json")
result = await classify.classify(path, archive_cache_dir=safe.StatePath(cache_dir))
assert result == classify.FileType.SOURCE
async def test_source_matcher_wins_over_npm_content_marker(tmp_path):
path = safe.RelPath("apache-widget-1.0.tgz")
cache_dir = _build_npm_pack_layout(tmp_path, name="apache-widget", version="1.0.0")
result = await classify.classify(
path,
base_path=safe.StatePath(tmp_path),
source_matcher=_always_true,
archive_cache_dir=safe.StatePath(cache_dir),
)
assert result == classify.FileType.SOURCE
async def test_source_matcher_wins_over_stem_binary(tmp_path):
path = safe.RelPath("apache-widget-1.0-bin.tar.gz")
result = await classify.classify(path, base_path=safe.StatePath(tmp_path), source_matcher=_always_true)
assert result == classify.FileType.SOURCE
async def test_source_stem_heuristic():
path = safe.RelPath("apache-widget-1.0-source.tar.gz")
assert (await classify.classify(path)) == classify.FileType.SOURCE
async def test_stem_heuristics_are_fallback_after_policy(tmp_path):
path = safe.RelPath("apache-widget-1.0-src.tar.gz")
result = await classify.classify(
path, base_path=safe.StatePath(tmp_path), source_matcher=_always_false, binary_matcher=_always_false
)
assert result == classify.FileType.SOURCE
def _always_false(_path: str) -> bool:
return False
def _always_true(_path: str) -> bool:
return True
def _build_npm_pack_layout(tmp_path, name: str, version: str):
cache_dir = tmp_path / "cache"
package_dir = cache_dir / "package"
package_dir.mkdir(parents=True)
(package_dir / "package.json").write_text(json.dumps({"name": name, "version": version}))
return cache_dir
def _matches_windows(path: str) -> bool:
return "windows" in path