package pdutil

import (
	"bytes"
	"errors"
	"io"
	"testing"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

func TestPdUtil(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "PdUtil Suite")
}

type errReader struct {
	io.Reader
}

func (errReader) Read(p []byte) (int, error) {
	return 0, errors.New("reading error")
}

type nopCloser struct {
	io.Reader
}

func (nopCloser) Close() error { return nil }

type errCloser struct {
	io.Reader
}

func (errCloser) Close() error { return errors.New("closing error") }

func justDeferClose(c io.Closer, err *error) {
	defer DeferClose(c, err)
}

var _ = Describe("Pkg/Util/Pdutil/Pdutil", func() {
	Describe("DeferClose", func() {
		Context("Existing error is empty", func() {
			It("should return no error", func() {
				body := nopCloser{bytes.NewBufferString("body")}
				var err error
				justDeferClose(body, &err)
				Expect(err).NotTo(HaveOccurred())
			})

			It("should return errors from closing", func() {
				body := errCloser{bytes.NewBufferString("body")}
				var err error
				justDeferClose(body, &err)
				Expect(err).To(HaveOccurred())
				Expect(err.Error()).To(Equal("closing error"))
			})
		})

		Context("Existing error", func() {
			It("should return no error", func() {
				body := nopCloser{bytes.NewBufferString("body")}
				err := errors.New("existing error")
				justDeferClose(body, &err)
				Expect(err).To(HaveOccurred())
				Expect(err.Error()).To(Equal("existing error"))
			})

			It("should return errors from closing", func() {
				body := errCloser{bytes.NewBufferString("body")}
				err := errors.New("existing error")
				justDeferClose(body, &err)
				Expect(err).To(HaveOccurred())
				Expect(err.Error()).To(Equal("existing error"))
			})
		})
	})

	Describe("readErrorBody", func() {
		It("should ready the body", func() {
			body := bytes.NewBufferString("body")
			err := readErrorBody(body)
			Expect(err).To(HaveOccurred())
			Expect(err.Error()).To(Equal("body"))
		})

		It("should return an error from reading the body", func() {
			body := errReader{bytes.NewBufferString("body")}
			err := readErrorBody(body)
			Expect(err).To(HaveOccurred())
			Expect(err.Error()).To(Equal("reading error"))
		})
	})
})
