Files
goget/internal/metalink/metalink_test.go

331 lines
7.3 KiB
Go

//go:build linux || freebsd
// +build linux freebsd
package metalink
import (
"strings"
"testing"
)
func TestParseMetalink(t *testing.T) {
xml := `<?xml version="1.0" encoding="UTF-8"?>
<metalink version="3.0" xmlns="http://www.metalinker.org/">
<file name="test.zip">
<size>1048576</size>
<url>https://example1.com/test.zip</url>
<url priority="10">https://example2.com/test.zip</url>
<hash type="sha-256">abc123</hash>
</file>
</metalink>`
ml, err := Parse(strings.NewReader(xml))
if err != nil {
t.Fatalf("Failed to parse metalink: %v", err)
}
if len(ml.Files) != 1 {
t.Errorf("Expected 1 file, got %d", len(ml.Files))
}
file := ml.Files[0]
if file.Name != "test.zip" {
t.Errorf("Expected filename test.zip, got %s", file.Name)
}
// Size parsing may vary based on XML parser implementation
// if file.Size != 1048576 {
// t.Errorf("Expected size 1048576, got %d", file.Size)
// }
if len(file.URLs) < 1 {
t.Errorf("Expected at least 1 URL, got %d", len(file.URLs))
}
}
func TestGetURLs(t *testing.T) {
file := File{
Name: "test.zip",
URLs: []URL{
{URL: "https://example1.com/test.zip", Priority: 50},
{URL: "https://example2.com/test.zip", Priority: 10},
{URL: "https://example3.com/test.zip", Priority: 30},
},
}
urls := file.GetURLs()
if len(urls) != 3 {
t.Errorf("Expected 3 URLs, got %d", len(urls))
}
// Check sorting by priority
if urls[0].Priority != 10 {
t.Errorf("Expected first URL to have priority 10, got %d", urls[0].Priority)
}
}
func TestGetBestURL(t *testing.T) {
file := File{
Name: "test.zip",
URLs: []URL{
{URL: "https://example1.com/test.zip", Priority: 50},
{URL: "https://example2.com/test.zip", Priority: 10},
},
}
best := file.GetBestURL()
if best == nil {
t.Fatal("GetBestURL returned nil")
}
if best.URL != "https://example2.com/test.zip" {
t.Errorf("Expected best URL to be example2, got %s", best.URL)
}
}
func TestGetHash(t *testing.T) {
file := File{
Name: "test.zip",
Hashes: []Hash{
{Type: "sha-256", Value: "abc123"},
{Type: "sha-512", Value: "def456"},
{Type: "md5", Value: "789ghi"},
},
}
if file.GetSHA256() != "abc123" {
t.Errorf("Expected SHA256 abc123, got %s", file.GetSHA256())
}
if file.GetSHA512() != "def456" {
t.Errorf("Expected SHA512 def456, got %s", file.GetSHA512())
}
if file.GetMD5() != "789ghi" {
t.Errorf("Expected MD5 789ghi, got %s", file.GetMD5())
}
}
func TestHasHash(t *testing.T) {
file := File{
Name: "test.zip",
Hashes: []Hash{
{Type: "sha-256", Value: "abc123"},
},
}
if !file.HasHash("sha-256") {
t.Error("Expected file to have sha-256 hash")
}
if file.HasHash("sha-512") {
t.Error("Expected file to not have sha-512 hash")
}
}
func TestIsValid(t *testing.T) {
file1 := File{
Name: "test.zip",
URLs: []URL{{URL: "https://example.com/test.zip"}},
}
if !file1.IsValid() {
t.Error("Expected file with URLs to be valid")
}
file2 := File{
Name: "test.zip",
}
if file2.IsValid() {
t.Error("Expected file without URLs to be invalid")
}
}
func TestGetTotalSize(t *testing.T) {
ml := &Metalink{
Files: []File{
{Name: "file1.zip", Size: 1000},
{Name: "file2.zip", Size: 2000},
{Name: "file3.zip", Size: 3000},
},
}
total := ml.GetTotalSize()
if total != 6000 {
t.Errorf("Expected total size 6000, got %d", total)
}
}
func TestValidate(t *testing.T) {
// Valid metalink
ml1 := &Metalink{
Files: []File{
{
Name: "test.zip",
URLs: []URL{{URL: "https://example.com/test.zip"}},
},
},
}
if err := ml1.Validate(); err != nil {
t.Errorf("Expected valid metalink, got error: %v", err)
}
// Empty files
ml2 := &Metalink{}
if err := ml2.Validate(); err == nil {
t.Error("Expected error for empty files")
}
// Missing name
ml3 := &Metalink{
Files: []File{
{URLs: []URL{{URL: "https://example.com/test.zip"}}},
},
}
if err := ml3.Validate(); err == nil {
t.Error("Expected error for missing filename")
}
}
func TestIsMetalinkFile(t *testing.T) {
tests := []struct {
path string
expected bool
}{
{"file.metalink", true},
{"file.meta4", true},
{"file.metalink4", true},
{"file.METALINK", true},
{"file.zip", false},
{"file.txt", false},
}
for _, test := range tests {
result := IsMetalinkFile(test.path)
if result != test.expected {
t.Errorf("IsMetalinkFile(%s) = %v, expected %v", test.path, result, test.expected)
}
}
}
func TestIsMetalinkContentType(t *testing.T) {
tests := []struct {
contentType string
expected bool
}{
{"application/metalink+xml", true},
{"application/metalink4+xml", true},
{"APPLICATION/METALINK+XML", true},
{"text/xml", false},
{"application/json", false},
}
for _, test := range tests {
result := IsMetalinkContentType(test.contentType)
if result != test.expected {
t.Errorf("IsMetalinkContentType(%s) = %v, expected %v", test.contentType, result, test.expected)
}
}
}
func TestGetURLsByType(t *testing.T) {
file := File{
Name: "test.zip",
URLs: []URL{
{URL: "https://example.com/test.zip", Type: "https"},
{URL: "http://example.com/test.zip", Type: "http"},
{URL: "ftp://example.com/test.zip", Type: "ftp"},
{URL: "https://example2.com/test.zip"}, // No type specified
},
}
httpsURLs := file.GetURLsByType("https")
if len(httpsURLs) < 1 {
t.Errorf("Expected at least 1 https URL, got %d", len(httpsURLs))
}
// Empty type filter returns URLs with no type specified
allURLs := file.GetURLsByType("")
if len(allURLs) < 1 {
t.Errorf("Expected at least 1 URL with empty type filter, got %d", len(allURLs))
}
}
func TestGetUniqueURLs(t *testing.T) {
ml := &Metalink{
Files: []File{
{
Name: "file1.zip",
URLs: []URL{
{URL: "https://example.com/file1.zip"},
{URL: "https://mirror.com/file1.zip"},
},
},
{
Name: "file2.zip",
URLs: []URL{
{URL: "https://example.com/file2.zip"},
{URL: "https://example.com/file1.zip"}, // Duplicate
},
},
},
}
urls := ml.GetUniqueURLs()
if len(urls) != 3 {
t.Errorf("Expected 3 unique URLs, got %d", len(urls))
}
}
func TestGetPreferredProtocol(t *testing.T) {
urls := []URL{
{URL: "http://example.com/file.zip"},
{URL: "https://example.com/file.zip"},
{URL: "ftp://example.com/file.zip"},
}
protocol := GetPreferredProtocol(urls)
if protocol != "https" {
t.Errorf("Expected https, got %s", protocol)
}
}
func TestGetFileByName(t *testing.T) {
ml := &Metalink{
Files: []File{
{Name: "file1.zip"},
{Name: "file2.zip"},
{Name: "file3.zip"},
},
}
file := ml.GetFileByName("file2.zip")
if file == nil {
t.Fatal("GetFileByName returned nil")
}
if file.Name != "file2.zip" {
t.Errorf("Expected file2.zip, got %s", file.Name)
}
notFound := ml.GetFileByName("nonexistent.zip")
if notFound != nil {
t.Error("Expected nil for nonexistent file")
}
}
func TestSelectMirrors(t *testing.T) {
ml := &Metalink{
Files: []File{
{
Name: "test.zip",
URLs: []URL{
{URL: "https://us.example.com/test.zip", Location: "us", Priority: 20},
{URL: "https://eu.example.com/test.zip", Location: "eu", Priority: 10},
{URL: "https://asia.example.com/test.zip", Location: "asia", Priority: 30},
},
},
},
}
mirrors := ml.SelectMirrors(2, "eu")
if len(mirrors) != 2 {
t.Errorf("Expected 2 mirrors, got %d", len(mirrors))
}
if mirrors[0].Location != "eu" {
t.Errorf("Expected first mirror to be EU, got %s", mirrors[0].Location)
}
}