331 lines
7.3 KiB
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)
|
||
|
|
}
|
||
|
|
}
|