1// Copyright 2014-2019 Ulrich Kunitz. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package lzma
6
7import (
8	"bytes"
9	"fmt"
10	"testing"
11)
12
13func TestChunkTypeString(t *testing.T) {
14	tests := [...]struct {
15		c chunkType
16		s string
17	}{
18		{cEOS, "EOS"},
19		{cUD, "UD"},
20		{cU, "U"},
21		{cL, "L"},
22		{cLR, "LR"},
23		{cLRN, "LRN"},
24		{cLRND, "LRND"},
25	}
26	for _, c := range tests {
27		s := fmt.Sprintf("%v", c.c)
28		if s != c.s {
29			t.Errorf("got %s; want %s", s, c.s)
30		}
31	}
32}
33
34func TestHeaderChunkType(t *testing.T) {
35	tests := []struct {
36		h byte
37		c chunkType
38	}{
39		{h: 0, c: cEOS},
40		{h: 1, c: cUD},
41		{h: 2, c: cU},
42		{h: 1<<7 | 0x1f, c: cL},
43		{h: 1<<7 | 1<<5 | 0x1f, c: cLR},
44		{h: 1<<7 | 1<<6 | 0x1f, c: cLRN},
45		{h: 1<<7 | 1<<6 | 1<<5 | 0x1f, c: cLRND},
46		{h: 1<<7 | 1<<6 | 1<<5, c: cLRND},
47	}
48	if _, err := headerChunkType(3); err == nil {
49		t.Fatalf("headerChunkType(%d) got %v; want %v",
50			3, err, errHeaderByte)
51	}
52	for _, tc := range tests {
53		c, err := headerChunkType(tc.h)
54		if err != nil {
55			t.Fatalf("headerChunkType error %s", err)
56		}
57		if c != tc.c {
58			t.Errorf("got %s; want %s", c, tc.c)
59		}
60	}
61}
62
63func TestHeaderLen(t *testing.T) {
64	tests := []struct {
65		c chunkType
66		n int
67	}{
68		{cEOS, 1}, {cU, 3}, {cUD, 3}, {cL, 5}, {cLR, 5}, {cLRN, 6},
69		{cLRND, 6},
70	}
71	for _, tc := range tests {
72		n := headerLen(tc.c)
73		if n != tc.n {
74			t.Errorf("header length for %s %d; want %d",
75				tc.c, n, tc.n)
76		}
77	}
78}
79
80func chunkHeaderSamples(t *testing.T) []chunkHeader {
81	props := Properties{LC: 3, LP: 0, PB: 2}
82	headers := make([]chunkHeader, 0, 12)
83	for c := cEOS; c <= cLRND; c++ {
84		var h chunkHeader
85		h.ctype = c
86		if c >= cUD {
87			h.uncompressed = 0x0304
88		}
89		if c >= cL {
90			h.compressed = 0x0201
91		}
92		if c >= cLRN {
93			h.props = props
94		}
95		headers = append(headers, h)
96	}
97	return headers
98}
99
100func TestChunkHeaderMarshalling(t *testing.T) {
101	for _, h := range chunkHeaderSamples(t) {
102		data, err := h.MarshalBinary()
103		if err != nil {
104			t.Fatalf("MarshalBinary for %v error %s", h, err)
105		}
106		var g chunkHeader
107		if err = g.UnmarshalBinary(data); err != nil {
108			t.Fatalf("UnmarshalBinary error %s", err)
109		}
110		if g != h {
111			t.Fatalf("got %v; want %v", g, h)
112		}
113	}
114}
115
116func TestReadChunkHeader(t *testing.T) {
117	for _, h := range chunkHeaderSamples(t) {
118		data, err := h.MarshalBinary()
119		if err != nil {
120			t.Fatalf("MarshalBinary for %v error %s", h, err)
121		}
122		r := bytes.NewReader(data)
123		g, err := readChunkHeader(r)
124		if err != nil {
125			t.Fatalf("readChunkHeader for %v error %s", h, err)
126		}
127		if *g != h {
128			t.Fatalf("got %v; want %v", g, h)
129		}
130	}
131}
132
133func TestReadEOS(t *testing.T) {
134	var b [1]byte
135	r := bytes.NewReader(b[:])
136	h, err := readChunkHeader(r)
137	if err != nil {
138		t.Fatalf("readChunkHeader error %s", err)
139	}
140	if h.ctype != cEOS {
141		t.Errorf("ctype got %s; want %s", h.ctype, cEOS)
142	}
143	if h.compressed != 0 {
144		t.Errorf("compressed got %d; want %d", h.compressed, 0)
145	}
146	if h.uncompressed != 0 {
147		t.Errorf("uncompressed got %d; want %d", h.uncompressed, 0)
148	}
149	wantProps := Properties{}
150	if h.props != wantProps {
151		t.Errorf("props got %v; want %v", h.props, wantProps)
152	}
153}
154