package ingest import ( "strings" "testing" ) // The decoder guards the one path in this zone that DESTROYS a user's file: intake reads a manifest // with no chapters in it as "the engine cut the source and there is no book in it", and removes the // upload. So a document that is not a manifest must not be able to arrive as an EMPTY manifest — // `{}`, `null` and a document of fields this build has never heard of all decode into the same zeros // otherwise. Found by the seam lens of the dofix review. // // The check is on the PRESENCE of the version and never on its value: pinning the value would make // every engine release a platform release, which is the reason it was left ungated in the first // place. // // Mutation caught: dropping the manifest_version check from DecodeManifest. func TestADocumentThatIsNotAManifestIsNotAnEmptyManifest(t *testing.T) { for _, body := range []string{ `{}`, `null`, `{"error":"the book is locked"}`, `{"chapters":[],"units":[]}`, `{"manifest_version":""}`, } { if _, err := DecodeManifest([]byte(body)); err == nil { t.Errorf("%s decoded as a manifest", body) } else if !strings.Contains(err.Error(), "manifest") { t.Errorf("%s: %v", body, err) } } // A manifest of a version this build has never seen is still a manifest: what it identifies as is // recorded, not judged. m, err := DecodeManifest([]byte(`{"manifest_version":"tm-manifest-v9","chapters_total":2283,"units_total":4402}`)) if err != nil { t.Fatalf("a manifest of a later version was refused: %v", err) } if m.ChaptersTotal != 2283 || m.Version != "tm-manifest-v9" { t.Fatalf("manifest = %+v", m) } // And a genuinely empty book decodes, because that is a real answer with a real consequence. if _, err := DecodeManifest([]byte(`{"manifest_version":"tm-manifest-v2","chapters_total":0}`)); err != nil { t.Fatalf("an empty book was refused: %v", err) } }