github.com/readium/readium-lcp-server@v0.0.0-20240101192032-6e95190e99f1/epub/writer_test.go (about)

     1  // Copyright (c) 2016 Readium Foundation
     2  //
     3  // Redistribution and use in source and binary forms, with or without modification,
     4  // are permitted provided that the following conditions are met:
     5  //
     6  // 1. Redistributions of source code must retain the above copyright notice, this
     7  //    list of conditions and the following disclaimer.
     8  // 2. Redistributions in binary form must reproduce the above copyright notice,
     9  //    this list of conditions and the following disclaimer in the documentation and/or
    10  //    other materials provided with the distribution.
    11  // 3. Neither the name of the organization nor the names of its contributors may be
    12  //    used to endorse or promote products derived from this software without specific
    13  //    prior written permission
    14  //
    15  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    16  // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    17  // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    18  // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
    19  // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    20  // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    21  // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
    22  // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    23  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    24  // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
    25  
    26  package epub
    27  
    28  import (
    29  	"archive/zip"
    30  	"bytes"
    31  	"fmt"
    32  	"io/ioutil"
    33  	"strings"
    34  	"testing"
    35  )
    36  
    37  const containerSpec = `<?xml version="1.0" encoding="UTF-8"?><container xmlns="urn:oasis:names:tc:opendocument:xmlns:container" version="1.0">
    38  <rootfiles>
    39  <rootfile full-path="EPUB/package.opf" media-type="application/oebps-package+xml"/>
    40  </rootfiles>
    41  </container>`
    42  
    43  const basicOpf = `
    44  <?xml version="1.0" encoding="UTF-8"?>
    45  <package xmlns="http://www.idpf.org/2007/opf" prefix="rendition: http://www.idpf.org/vocab/rendition/# cc: http://creativecommons.org/ns#" version="3.0" unique-identifier="bookid" xml:lang="fr" dir="ltr" id="package">
    46  	<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
    47  		<dc:identifier id="bookid">test-basic-epub</dc:identifier>
    48  		<dc:language>fr</dc:language>
    49  	</metadata>
    50  	<manifest>
    51  		<item id="page" href="page.xhtml" media-type="application/xhtml+xml"/>
    52  	</manifest>
    53  	<spine>
    54  		<itemref idref="page"/>
    55  	</spine>
    56  </package>`
    57  
    58  const basicPage = `
    59  <?xml version="1.0" encoding="UTF-8"?>
    60  <!DOCTYPE html>
    61  <html>
    62  <body>Hello</body>
    63  </htmL>`
    64  
    65  func createBasicEpub() Epub {
    66  	var ep Epub
    67  	ep.Add(ContainerFile, strings.NewReader(containerSpec), uint64(len(containerSpec)))
    68  
    69  	ep.Add("EPUB/package.opf", strings.NewReader(basicOpf), uint64(len(basicOpf)))
    70  
    71  	ep.Add("EPUB/page.xhtml", strings.NewReader(basicPage), uint64(len(basicPage)))
    72  
    73  	return ep
    74  }
    75  
    76  func TestWriteBasicEpub(t *testing.T) {
    77  	ep := createBasicEpub()
    78  
    79  	// Mark the page as already-compressed
    80  	ep.Resource[len(ep.Resource)-1].Compressed = true
    81  
    82  	var buf bytes.Buffer
    83  	ep.Write(&buf)
    84  
    85  	r := bytes.NewReader(buf.Bytes())
    86  	zr, err := zip.NewReader(r, int64(buf.Len()))
    87  
    88  	if err != nil {
    89  		t.Fatal("Could not read zip", err)
    90  	}
    91  
    92  	out, err := Read(zr)
    93  	if err != nil {
    94  		t.Fatal("Could not construct epub from zip", err)
    95  	}
    96  
    97  	if l := len(out.Resource); l != 3 {
    98  		t.Fatalf("Expected 3 resources, got %d", l)
    99  	}
   100  
   101  	for i, r := range ep.Resource {
   102  		if equiv := out.Resource[i]; r.Path != equiv.Path {
   103  			t.Errorf("Expected %s, got %s", r.Path, equiv.Path)
   104  		}
   105  	}
   106  
   107  	testContentsOfFileInZip(t, zr, zip.Store, "mimetype", ContentType_EPUB)
   108  	testContentsOfFileInZip(t, zr, zip.Deflate, ContainerFile, containerSpec)
   109  	testContentsOfFileInZip(t, zr, zip.Deflate, "EPUB/package.opf", basicOpf)
   110  	testContentsOfFileInZip(t, zr, zip.Deflate, "EPUB/page.xhtml", basicPage)
   111  }
   112  
   113  func testContentsOfFileInZip(t *testing.T, zr *zip.Reader, m uint16, path, expected string) {
   114  	for _, f := range zr.File {
   115  		fmt.Println(f.Name)
   116  	}
   117  
   118  	if f, err := findFileInZip(zr, path); err != nil {
   119  		t.Fatalf("Could not find %s in file", path)
   120  	} else {
   121  		if meth := f.FileHeader.Method; meth != m {
   122  			t.Errorf("Expected %s to have method %d, got %d", path, m, meth)
   123  		}
   124  
   125  		r, err := f.Open()
   126  		if err != nil {
   127  			t.Fatalf("Could not open %s", path)
   128  		}
   129  		defer r.Close()
   130  
   131  		if bb, err := ioutil.ReadAll(r); err != nil {
   132  			t.Fatalf("Could not read %s", path)
   133  		} else {
   134  			if string(bb) != expected {
   135  				t.Errorf("Expected %s to contain %s, got %s", path, expected, string(bb))
   136  			}
   137  		}
   138  	}
   139  }