// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package lzw

import (
	"io"
	"io/ioutil"
	"os"
	"runtime"
	"testing"
)

var filenames = []string{
	"../testdata/e.txt",
	"../testdata/pi.txt",
}

// testFile tests that compressing and then decompressing the given file with
// the given options yields equivalent bytes to the original file.
func testFile(t *testing.T, fn string, order Order, litWidth int) {
	// Read the file, as golden output.
	golden, err := os.Open(fn)
	if err != nil {
		t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err)
		return
	}
	defer golden.Close()

	// Read the file again, and push it through a pipe that compresses at the write end, and decompresses at the read end.
	raw, err := os.Open(fn)
	if err != nil {
		t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err)
		return
	}

	piper, pipew := io.Pipe()
	defer piper.Close()
	go func() {
		defer raw.Close()
		defer pipew.Close()
		lzww := NewWriter(pipew, order, litWidth)
		defer lzww.Close()
		var b [4096]byte
		for {
			n, err0 := raw.Read(b[:])
			if err0 != nil && err0 != os.EOF {
				t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err0)
				return
			}
			_, err1 := lzww.Write(b[:n])
			if err1 == os.EPIPE {
				// Fail, but do not report the error, as some other (presumably reportable) error broke the pipe.
				return
			}
			if err1 != nil {
				t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err1)
				return
			}
			if err0 == os.EOF {
				break
			}
		}
	}()
	lzwr := NewReader(piper, order, litWidth)
	defer lzwr.Close()

	// Compare the two.
	b0, err0 := ioutil.ReadAll(golden)
	b1, err1 := ioutil.ReadAll(lzwr)
	if err0 != nil {
		t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err0)
		return
	}
	if err1 != nil {
		t.Errorf("%s (order=%d litWidth=%d): %v", fn, order, litWidth, err1)
		return
	}
	if len(b1) != len(b0) {
		t.Errorf("%s (order=%d litWidth=%d): length mismatch %d != %d", fn, order, litWidth, len(b1), len(b0))
		return
	}
	for i := 0; i < len(b0); i++ {
		if b1[i] != b0[i] {
			t.Errorf("%s (order=%d litWidth=%d): mismatch at %d, 0x%02x != 0x%02x\n", fn, order, litWidth, i, b1[i], b0[i])
			return
		}
	}
}

func TestWriter(t *testing.T) {
	for _, filename := range filenames {
		for _, order := range [...]Order{LSB, MSB} {
			// The test data "2.71828 etcetera" is ASCII text requiring at least 6 bits.
			for _, litWidth := range [...]int{6, 7, 8} {
				testFile(t, filename, order, litWidth)
			}
		}
	}
}

func benchmarkEncoder(b *testing.B, n int) {
	b.StopTimer()
	b.SetBytes(int64(n))
	buf0, _ := ioutil.ReadFile("../testdata/e.txt")
	buf0 = buf0[:10000]
	buf1 := make([]byte, n)
	for i := 0; i < n; i += len(buf0) {
		copy(buf1[i:], buf0)
	}
	buf0 = nil
	runtime.GC()
	b.StartTimer()
	for i := 0; i < b.N; i++ {
		w := NewWriter(ioutil.Discard, LSB, 8)
		w.Write(buf1)
		w.Close()
	}
}

func BenchmarkEncoder1e4(b *testing.B) {
	benchmarkEncoder(b, 1e4)
}

func BenchmarkEncoder1e5(b *testing.B) {
	benchmarkEncoder(b, 1e5)
}

func BenchmarkEncoder1e6(b *testing.B) {
	benchmarkEncoder(b, 1e6)
}
