erplibre/script/qemu_cache/instantane_test.go

142 lines
4.8 KiB
Go
Raw Permalink Normal View History

// © 2026 TechnoLibre (http://www.technolibre.ca)
// License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
package main
import (
"net/http"
"net/url"
"testing"
)
// vendredi et samedi : deux instantanés d'un dépôt apt, à un jour d'écart.
const (
vendredi = "Fri, 11 Sep 2026 07:18:59 GMT"
samedi = "Sat, 12 Sep 2026 13:06:19 GMT"
)
// garnir range un corps sous son URL, avec la date que l'amont lui donne.
func garnir(t *testing.T, p *Proxy, brut, corps, lastModified string) {
t.Helper()
u, err := url.Parse(brut)
if err != nil {
t.Fatal(err)
}
w, err := p.Store.NewWriter(CleDe("GET", u), Meta{
URL: u.String(), Method: "GET", Status: http.StatusOK,
Header: http.Header{"Last-Modified": []string{lastModified}},
Class: ClassVolatile.String(),
})
if err != nil {
t.Fatal(err)
}
if _, err := w.Write([]byte(corps)); err != nil {
t.Fatal(err)
}
if err := w.Commit(int64(len(corps))); err != nil {
t.Fatal(err)
}
}
// Un index plus récent que la signature qui l'annonce n'est pas servi.
//
// apt exige de chaque index la taille et la somme écrites dans la
// signature : un index pris à un autre instantané le fait échouer sur
// « File has unexpected size », et l'installation s'arrête plus bas sur des
// dépendances introuvables — un message qui accuse le dépôt, jamais le
// cache.
func TestUnIndexPlusRecentQueSaSignatureNeSortPas(t *testing.T) {
a := nouvelAmont(t, "peu importe")
p := proxyDeTest(t)
base := "http://" + a.hote() + "/ubuntu/dists/resolute-updates/"
garnir(t, p, base+"InRelease", "signature de vendredi", vendredi)
garnir(t, p, base+"main/binary-amd64/Packages.xz", "index de samedi", samedi)
hote := a.hote()
a.srv.Close()
w := joue(t, p, "GET", hote, "/ubuntu/dists/resolute-updates/InRelease")
if w.Code != http.StatusOK {
t.Fatalf("la signature gardée doit sortir : code %d", w.Code)
}
w = joue(t, p, "GET", hote,
"/ubuntu/dists/resolute-updates/main/binary-amd64/Packages.xz")
if w.Code == http.StatusOK {
t.Errorf("l'index de samedi est sorti sous la signature de vendredi")
}
}
// L'inverse est le cas NORMAL : les deux viennent du même passage en ligne,
// et refuser de servir là romprait le déploiement hors ligne.
func TestUnIndexAussiVieuxQueSaSignatureSort(t *testing.T) {
a := nouvelAmont(t, "peu importe")
p := proxyDeTest(t)
base := "http://" + a.hote() + "/ubuntu/dists/resolute/"
garnir(t, p, base+"InRelease", "signature", vendredi)
garnir(t, p, base+"main/binary-amd64/Packages.xz", "index", vendredi)
hote := a.hote()
a.srv.Close()
w := joue(t, p, "GET", hote,
"/ubuntu/dists/resolute/main/binary-amd64/Packages.xz")
if w.Code != http.StatusOK || w.Body.String() != "index" {
t.Fatalf("code %d, corps %q : l'index du même instantané doit sortir",
w.Code, w.Body.String())
}
}
// Un objet adressé par son contenu ne se juge pas : son nom EST sa somme,
// et apt l'accepte quelle que soit la date de la signature.
func TestUnObjetParEmpreinteSortQuandMeme(t *testing.T) {
a := nouvelAmont(t, "peu importe")
p := proxyDeTest(t)
base := "http://" + a.hote() + "/ubuntu/dists/resolute-updates/"
garnir(t, p, base+"InRelease", "signature de vendredi", vendredi)
parHash := base + "main/binary-amd64/by-hash/SHA256/" +
"e55707cc7a5ad03d7f700ccb6646fd5c6ecbc852c4c826f5edbb5a321358d0ee"
garnir(t, p, parHash, "index de samedi", samedi)
hote := a.hote()
a.srv.Close()
w := joue(t, p, "GET", hote,
"/ubuntu/dists/resolute-updates/main/binary-amd64/by-hash/SHA256/"+
"e55707cc7a5ad03d7f700ccb6646fd5c6ecbc852c4c826f5edbb5a321358d0ee")
if w.Code != http.StatusOK {
t.Errorf("un objet par empreinte a été retenu : code %d", w.Code)
}
}
// Sans signature gardée, il n'y a rien à contredire : l'index gardé est tout
// ce que le hors-ligne possède, et le retenir ne servirait personne.
func TestSansSignatureLIndexSortQuandMeme(t *testing.T) {
a := nouvelAmont(t, "peu importe")
p := proxyDeTest(t)
garnir(t, p, "http://"+a.hote()+
"/ubuntu/dists/orpheline/main/binary-amd64/Packages.xz",
"index seul", samedi)
hote := a.hote()
a.srv.Close()
w := joue(t, p, "GET", hote,
"/ubuntu/dists/orpheline/main/binary-amd64/Packages.xz")
if w.Code != http.StatusOK || w.Body.String() != "index seul" {
t.Errorf("code %d, corps %q : l'index sans signature doit sortir",
w.Code, w.Body.String())
}
}
// Hors de « /dists/ », aucune signature n'entre en jeu : un paquet ne se
// juge pas sur la date d'un index.
func TestHorsDeDistsRienNestJuge(t *testing.T) {
a := nouvelAmont(t, "peu importe")
p := proxyDeTest(t)
garnir(t, p, "http://"+a.hote()+"/ubuntu/pool/main/x/xz_5.6_amd64.deb",
"le paquet", samedi)
hote := a.hote()
a.srv.Close()
w := joue(t, p, "GET", hote, "/ubuntu/pool/main/x/xz_5.6_amd64.deb")
if w.Code != http.StatusOK {
t.Errorf("un paquet a été retenu : code %d", w.Code)
}
}