aboutsummaryrefslogtreecommitdiff
path: root/mountain_pass/fetch_test.go
diff options
context:
space:
mode:
authorMartin Kagamino Lehoux <martin@lehoux.net>2026-08-24 14:19:01 +0200
committerMartin Kagamino Lehoux <martin@lehoux.net>2026-08-24 14:19:01 +0200
commit9c2337b50a52ee95011028f6193e0c56aa1fc9d4 (patch)
tree13f391fa4bc6a96c32522204235ff3ea83855927 /mountain_pass/fetch_test.go
parent4dcc0a4e655b0178a7733954bf75df3cff9ef07a (diff)
Verify downloaded France OSM PBF against geofabrik's published MD5
Diffstat (limited to 'mountain_pass/fetch_test.go')
-rw-r--r--mountain_pass/fetch_test.go121
1 files changed, 121 insertions, 0 deletions
diff --git a/mountain_pass/fetch_test.go b/mountain_pass/fetch_test.go
new file mode 100644
index 0000000..0e6304a
--- /dev/null
+++ b/mountain_pass/fetch_test.go
@@ -0,0 +1,121 @@
+package mountain_pass
+
+import (
+ "crypto/md5"
+ "encoding/hex"
+ "net/http"
+ "net/http/httptest"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
+)
+
+// osmd5Hex mirrors the production helper in the test so the expected checksum
+// served by the fake geofabrik server is derived independently of pbfMD5.
+func osmd5Hex(data []byte) string {
+ sum := md5.Sum(data)
+ return hex.EncodeToString(sum[:])
+}
+
+// fakeGeofabrik serves a PBF payload and an optional .md5 sibling.
+func fakeGeofabrik(t *testing.T, pbf []byte, md5Body string) *httptest.Server {
+ t.Helper()
+ mux := http.NewServeMux()
+ mux.HandleFunc("/france-latest.osm.pbf", func(w http.ResponseWriter, r *http.Request) {
+ w.Write(pbf)
+ })
+ mux.HandleFunc("/france-latest.osm.pbf.md5", func(w http.ResponseWriter, r *http.Request) {
+ if md5Body == "" {
+ http.Error(w, "not found", http.StatusNotFound)
+ return
+ }
+ w.Write([]byte(md5Body))
+ })
+ srv := httptest.NewServer(mux)
+ t.Cleanup(srv.Close)
+ return srv
+}
+
+func TestFetchFrancePBFDownloadsAndVerifies(t *testing.T) {
+ pbf := []byte("some-valid-pbf-content-1")
+ srv := fakeGeofabrik(t, pbf, osmd5Hex(pbf)+" france-latest.osm.pbf\n")
+ dest := filepath.Join(t.TempDir(), "france-latest.osm.pbf")
+
+ err := fetchFrancePBF(srv.Client(), srv.URL+"/france-latest.osm.pbf", dest)
+ require.NoError(t, err)
+
+ got, err := os.ReadFile(dest)
+ require.NoError(t, err)
+ assert.Equal(t, pbf, got)
+}
+
+func TestFetchFrancePBFMismatchRetainsFile(t *testing.T) {
+ pbf := []byte("some-valid-pbf-content-2")
+ srv := fakeGeofabrik(t, pbf, strings.Repeat("0", 32)+" france-latest.osm.pbf\n")
+ dest := filepath.Join(t.TempDir(), "france-latest.osm.pbf")
+
+ err := fetchFrancePBF(srv.Client(), srv.URL+"/france-latest.osm.pbf", dest)
+ require.Error(t, err)
+ assert.Contains(t, err.Error(), "checksum mismatch")
+
+ // The corrupt file is kept for inspection, not deleted.
+ got, readErr := os.ReadFile(dest)
+ require.NoError(t, readErr)
+ assert.Equal(t, pbf, got)
+}
+
+func TestFetchFrancePBFAlreadyCompleteVerified(t *testing.T) {
+ pbf := []byte("some-valid-pbf-content-3")
+ srv := fakeGeofabrik(t, pbf, osmd5Hex(pbf)+" france-latest.osm.pbf\n")
+ dest := filepath.Join(t.TempDir(), "france-latest.osm.pbf")
+ require.NoError(t, os.WriteFile(dest, pbf, 0o644))
+
+ err := fetchFrancePBF(srv.Client(), srv.URL+"/france-latest.osm.pbf", dest)
+ require.NoError(t, err)
+
+ got, _ := os.ReadFile(dest)
+ assert.Equal(t, pbf, got)
+}
+
+func TestFetchFrancePBFAlreadyCompleteCorrupt(t *testing.T) {
+ pbf := []byte("the-real-content")
+ corrupt := []byte(strings.Repeat("x", len(pbf)))
+ require.Equal(t, len(pbf), len(corrupt), "same length to prove size-only check is not enough")
+ srv := fakeGeofabrik(t, pbf, osmd5Hex(pbf)+" france-latest.osm.pbf\n")
+ dest := filepath.Join(t.TempDir(), "france-latest.osm.pbf")
+ require.NoError(t, os.WriteFile(dest, corrupt, 0o644))
+
+ err := fetchFrancePBF(srv.Client(), srv.URL+"/france-latest.osm.pbf", dest)
+ require.Error(t, err)
+ assert.Contains(t, err.Error(), "checksum mismatch")
+
+ got, _ := os.ReadFile(dest)
+ assert.Equal(t, corrupt, got, "corrupt file retained for inspection")
+}
+
+func TestFetchFrancePBFSkipsVerificationWhenChecksumUnreachable(t *testing.T) {
+ pbf := []byte("some-valid-pbf-content-4")
+ srv := fakeGeofabrik(t, pbf, "") // md5 endpoint returns 404
+ dest := filepath.Join(t.TempDir(), "france-latest.osm.pbf")
+
+ err := fetchFrancePBF(srv.Client(), srv.URL+"/france-latest.osm.pbf", dest)
+ require.NoError(t, err)
+
+ got, _ := os.ReadFile(dest)
+ assert.Equal(t, pbf, got)
+}
+
+func TestPBFMD5(t *testing.T) {
+ data := []byte("known-content-for-md5-test")
+ expected := osmd5Hex(data)
+ path := filepath.Join(t.TempDir(), "sample.bin")
+ require.NoError(t, os.WriteFile(path, data, 0o644))
+
+ got, err := pbfMD5(path)
+ require.NoError(t, err)
+ assert.Equal(t, expected, got)
+}