mscfb_test.go 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. package mscfb
  2. import (
  3. "bytes"
  4. "io"
  5. "io/ioutil"
  6. "os"
  7. "testing"
  8. )
  9. var (
  10. novPapPlan = "test/novpapplan.doc"
  11. testDoc = "test/test.doc"
  12. testXls = "test/test.xls"
  13. testPpt = "test/test.ppt"
  14. testMsg = "test/test.msg"
  15. testEntries = []*File{
  16. &File{Name: "Root Node",
  17. directoryEntryFields: &directoryEntryFields{leftSibID: noStream, rightSibID: noStream, childID: 1},
  18. },
  19. &File{Name: "Alpha",
  20. directoryEntryFields: &directoryEntryFields{leftSibID: noStream, rightSibID: 2, childID: noStream},
  21. },
  22. &File{Name: "Bravo",
  23. directoryEntryFields: &directoryEntryFields{leftSibID: noStream, rightSibID: 3, childID: 5},
  24. },
  25. &File{Name: "Charlie",
  26. directoryEntryFields: &directoryEntryFields{leftSibID: noStream, rightSibID: noStream, childID: 7},
  27. },
  28. &File{Name: "Delta",
  29. directoryEntryFields: &directoryEntryFields{leftSibID: noStream, rightSibID: noStream, childID: noStream},
  30. },
  31. &File{Name: "Echo",
  32. directoryEntryFields: &directoryEntryFields{leftSibID: 4, rightSibID: 6, childID: 9},
  33. },
  34. &File{Name: "Foxtrot",
  35. directoryEntryFields: &directoryEntryFields{leftSibID: noStream, rightSibID: noStream, childID: noStream},
  36. },
  37. &File{Name: "Golf",
  38. directoryEntryFields: &directoryEntryFields{leftSibID: noStream, rightSibID: noStream, childID: 10},
  39. },
  40. &File{Name: "Hotel",
  41. directoryEntryFields: &directoryEntryFields{leftSibID: noStream, rightSibID: noStream, childID: noStream},
  42. },
  43. &File{Name: "Indigo",
  44. directoryEntryFields: &directoryEntryFields{leftSibID: 8, rightSibID: noStream, childID: 11},
  45. },
  46. &File{Name: "Jello",
  47. directoryEntryFields: &directoryEntryFields{leftSibID: noStream, rightSibID: noStream, childID: noStream},
  48. },
  49. &File{Name: "Kilo",
  50. directoryEntryFields: &directoryEntryFields{leftSibID: noStream, rightSibID: noStream, childID: noStream},
  51. },
  52. }
  53. )
  54. func equals(a, b []int) bool {
  55. if len(a) != len(b) {
  56. return false
  57. }
  58. for i, v := range a {
  59. if v != b[i] {
  60. return false
  61. }
  62. }
  63. return true
  64. }
  65. func empty(sl []byte) bool {
  66. for _, v := range sl {
  67. if v != 0 {
  68. return false
  69. }
  70. }
  71. return true
  72. }
  73. func testFile(t *testing.T, path string) {
  74. file, _ := os.Open(path)
  75. defer file.Close()
  76. doc, err := New(file)
  77. if err != nil {
  78. t.Fatalf("Error opening file; Returns error: %v", err)
  79. }
  80. if len(doc.File) < 3 {
  81. t.Fatalf("Expecting several directory entries, only got %d", len(doc.File))
  82. }
  83. buf := make([]byte, 512)
  84. for entry, _ := doc.Next(); entry != nil; entry, _ = doc.Next() {
  85. _, err := doc.Read(buf)
  86. if err != nil && err != io.EOF {
  87. t.Errorf("Error reading entry name, %v", entry.Name)
  88. }
  89. if len(entry.Name) < 1 {
  90. t.Errorf("Error reading entry name")
  91. }
  92. }
  93. }
  94. func TestTraverse(t *testing.T) {
  95. r := new(Reader)
  96. r.direntries = testEntries
  97. if r.traverse() != nil {
  98. t.Error("Error traversing")
  99. }
  100. expect := []int{0, 1, 2, 4, 5, 8, 9, 11, 6, 3, 7, 10}
  101. if len(r.File) != len(expect) {
  102. t.Fatalf("Error traversing: expecting %d entries, got %d", len(expect), len(r.File))
  103. }
  104. for i, v := range r.File {
  105. if v != testEntries[expect[i]] {
  106. t.Errorf("Error traversing: expecting %d at index %d; got %v", expect[i], i, v)
  107. }
  108. }
  109. if len(r.File[len(r.File)-1].Path) != 2 {
  110. t.Fatalf("Error traversing: expecting a path length of %d, got %d", 2, len(r.File[len(r.File)-1].Path))
  111. }
  112. if r.File[len(r.File)-1].Path[0] != "Charlie" {
  113. t.Errorf("Error traversing: expecting Charlie got %s", r.File[expect[10]].Path[0])
  114. }
  115. if r.File[len(r.File)-1].Path[1] != "Golf" {
  116. t.Errorf("Error traversing: expecting Golf got %s", r.File[expect[10]].Path[1])
  117. }
  118. }
  119. func TestNovPapPlan(t *testing.T) {
  120. testFile(t, novPapPlan)
  121. }
  122. func TestWord(t *testing.T) {
  123. testFile(t, testDoc)
  124. }
  125. func TestMsg(t *testing.T) {
  126. testFile(t, testMsg)
  127. }
  128. func TestPpt(t *testing.T) {
  129. testFile(t, testPpt)
  130. }
  131. func TestXls(t *testing.T) {
  132. testFile(t, testXls)
  133. }
  134. func TestSeek(t *testing.T) {
  135. file, _ := os.Open(testXls)
  136. defer file.Close()
  137. doc, _ := New(file)
  138. // the third entry in the XLS file is 2719 bytes
  139. f := doc.File[3]
  140. if f.Size != 2719 {
  141. t.Fatalf("Expecting the third entry of the XLS file to be 2719 bytes long; it is %d", f.Size)
  142. }
  143. buf := make([]byte, 2719)
  144. i, err := f.Read(buf)
  145. if i != 2719 || err != nil {
  146. t.Fatalf("Expecting 2719 length and no error; got %d and %v", i, err)
  147. }
  148. s, err := f.Seek(50, 1)
  149. if s != 2719 || err == nil {
  150. t.Fatalf("%v, %d", err, s)
  151. }
  152. s, err = f.Seek(1500, 0)
  153. if s != 1500 || err != nil {
  154. t.Fatalf("Seek error: %v, %d", err, s)
  155. }
  156. nbuf := make([]byte, 475)
  157. i, err = f.Read(nbuf)
  158. if i != 475 || err != nil {
  159. t.Fatalf("Expecting 475 length and no error; got %d and %v", i, err)
  160. }
  161. if !bytes.Equal(buf[1500:1975], nbuf) {
  162. t.Fatalf("Slices not equal: %s, %s", string(buf[1500:1975]), string(nbuf))
  163. }
  164. s, err = f.Seek(5, 1)
  165. if s != 1980 || err != nil {
  166. t.Fatalf("Seek error: %v, %d", err, s)
  167. }
  168. i, err = f.Read(nbuf[:5])
  169. if i != 5 || err != nil {
  170. t.Fatalf("Expecting 5 length, and no error; got %d and %v", i, err)
  171. }
  172. if !bytes.Equal(buf[1980:1985], nbuf[:5]) {
  173. t.Fatalf("Slices not equal: %s, %s", string(buf[1980:1985]), string(nbuf[:5]))
  174. }
  175. s, err = f.Seek(30, 2)
  176. if s != 2689 || err != nil {
  177. t.Fatalf("Seek error: %v, %d", err, s)
  178. }
  179. i, err = f.Read(nbuf[:30])
  180. if i != 30 || err != nil {
  181. t.Fatalf("Expecting 30 length, and no error; got %d and %v", i, err)
  182. }
  183. if !bytes.Equal(buf[2689:], nbuf[:30]) {
  184. t.Fatalf("Slices not equal: %d, %s, %s", len(buf[2688:]), string(buf[2688:]), string(nbuf[:30]))
  185. }
  186. }
  187. func TestWrite(t *testing.T) {
  188. file, err := os.OpenFile(testXls, os.O_RDWR, 0666)
  189. if err != nil {
  190. t.Fatalf("error opening file for read/write %v", err)
  191. }
  192. defer file.Close()
  193. doc, err := New(file)
  194. if err != nil {
  195. t.Fatalf("Error opening file; Returns error: %v", err)
  196. }
  197. // the third entry in the XLS file is 2719 bytes
  198. f := doc.File[3]
  199. s, err := f.Seek(30, 0)
  200. if s != 30 || err != nil {
  201. t.Fatalf("Seek error: %v, %d", err, s)
  202. }
  203. orig := make([]byte, 4)
  204. i, err := f.Read(orig)
  205. if i != 4 || err != nil {
  206. t.Fatalf("Expecting read length 4, and no error, got %d %v", i, err)
  207. }
  208. s, err = f.Seek(30, 0)
  209. if s != 30 || err != nil {
  210. t.Fatalf("Seek error: %v, %d", err, s)
  211. }
  212. i, err = f.Write([]byte("test"))
  213. if i != 4 || err != nil {
  214. t.Errorf("error writing, got %d %v", i, err)
  215. }
  216. s, err = f.Seek(30, 0)
  217. if s != 30 || err != nil {
  218. t.Fatalf("Seek error: %v, %d", err, s)
  219. }
  220. res := make([]byte, 4)
  221. i, err = f.Read(res)
  222. if i != 4 || err != nil {
  223. t.Errorf("error reading, got %d %v", i, err)
  224. }
  225. if string(res) != "test" {
  226. t.Errorf("expecting test, got %s", string(res))
  227. }
  228. s, err = f.Seek(30, 0)
  229. if s != 30 || err != nil {
  230. t.Fatalf("Seek error: %v, %d", err, s)
  231. }
  232. i, err = f.Write(orig)
  233. if i != 4 || err != nil {
  234. t.Errorf("error writing, got %d %v", i, err)
  235. }
  236. s, err = f.Seek(30, 0)
  237. if s != 30 || err != nil {
  238. t.Fatalf("Seek error: %v, %d", err, s)
  239. }
  240. i, err = f.Read(res)
  241. if i != 4 || err != nil {
  242. t.Errorf("error reading, got %d %v", i, err)
  243. }
  244. if string(res) != string(orig) {
  245. t.Errorf("bad result, expected %s, got %s", string(orig), string(res))
  246. }
  247. i, err = f.WriteAt([]byte("test"), 30)
  248. if i != 4 || err != nil {
  249. t.Errorf("error writing, got %d %v", i, err)
  250. }
  251. i, err = f.ReadAt(res, 30)
  252. if i != 4 || err != nil {
  253. t.Errorf("error reading, got %d %v", i, err)
  254. }
  255. if string(res) != "test" {
  256. t.Errorf("expecting test, got %s", string(res))
  257. }
  258. i, err = f.WriteAt(orig, 30)
  259. if i != 4 || err != nil {
  260. t.Errorf("error writing, got %d %v", i, err)
  261. }
  262. i, err = f.ReadAt(res, 30)
  263. if i != 4 || err != nil {
  264. t.Errorf("error reading, got %d %v", i, err)
  265. }
  266. if string(res) != string(orig) {
  267. t.Errorf("bad result, expected %s, got %s", string(orig), string(res))
  268. }
  269. }
  270. func benchFile(b *testing.B, path string) {
  271. b.StopTimer()
  272. buf, _ := ioutil.ReadFile(path)
  273. entrybuf := make([]byte, 32000)
  274. b.StartTimer()
  275. rdr := bytes.NewReader(buf)
  276. for i := 0; i < b.N; i++ {
  277. doc, _ := New(rdr)
  278. for entry, _ := doc.Next(); entry != nil; entry, _ = doc.Next() {
  279. doc.Read(entrybuf)
  280. }
  281. }
  282. }
  283. func BenchmarkNovPapPlan(b *testing.B) {
  284. benchFile(b, novPapPlan)
  285. }
  286. func BenchmarkWord(b *testing.B) {
  287. benchFile(b, testDoc)
  288. }
  289. func BenchmarkMsg(b *testing.B) {
  290. benchFile(b, testMsg)
  291. }
  292. func BenchmarkPpt(b *testing.B) {
  293. benchFile(b, testPpt)
  294. }
  295. func BenchmarkXls(b *testing.B) {
  296. benchFile(b, testXls)
  297. }
  298. /*
  299. 22/12
  300. BenchmarkNovPapPlan 50000 31676 ns/op
  301. BenchmarkWord 20000 65693 ns/op
  302. BenchmarkMsg 10000 198380 ns/op
  303. BenchmarkPpt 50000 30156 ns/op
  304. BenchmarkXls 100000 20327 ns/op
  305. */