/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package thrift

import (
	"errors"
	"fmt"
	"io"
	"testing"
)

type timeout struct{ timedout bool }

func (t *timeout) Timeout() bool {
	return t.timedout
}

func (t *timeout) Error() string {
	return fmt.Sprintf("Timeout: %v", t.timedout)
}

func TestTExceptionTimeout(t *testing.T) {
	timeout := &timeout{true}
	exception := NewTTransportExceptionFromError(timeout)
	if timeout.Error() != exception.Error() {
		t.Errorf("Error did not match: expected %q, got %q", timeout.Error(), exception.Error())
	}

	if exception.TypeId() != TIMED_OUT {
		t.Errorf("TypeId was not TIMED_OUT: expected %v, got %v", TIMED_OUT, exception.TypeId())
	}

	// NOTE: this can also be replaced by errors.Unwrap, but that requires
	// go 1.13+.
	if e, ok := exception.(unwrapper); !ok {
		t.Error("Expected exception to be unwrappable, it is not.")
	} else if e.Unwrap() != timeout {
		t.Errorf("Unwrapped exception did not match: expected %v, got %v", timeout, e.Unwrap())
	}
}

func TestTExceptionEOF(t *testing.T) {
	exception := NewTTransportExceptionFromError(io.EOF)
	if io.EOF.Error() != exception.Error() {
		t.Errorf("Error did not match: expected %q, got %q", io.EOF.Error(), exception.Error())
	}

	if exception.TypeId() != END_OF_FILE {
		t.Errorf("TypeId was not END_OF_FILE: expected %v, got %v", END_OF_FILE, exception.TypeId())
	}

	// NOTE: this can also be replaced by errors.Unwrap, but that requires
	// go 1.13+.
	if e, ok := exception.(unwrapper); !ok {
		t.Error("Expected exception to be unwrappable, it is not.")
	} else if e.Unwrap() != io.EOF {
		t.Errorf("Unwrapped exception did not match: expected %v, got %v", io.EOF, e.Unwrap())
	}
}

func TestIsTimeoutError(t *testing.T) {
	te := &timeout{true}
	if !isTimeoutError(te) {
		t.Error("isTimeoutError expected true, got false")
	}
	e := NewTTransportExceptionFromError(te)
	if !isTimeoutError(e) {
		t.Error("isTimeoutError on wrapped TTransportException expected true, got false")
	}

	te = &timeout{false}
	if isTimeoutError(te) {
		t.Error("isTimeoutError expected false, got true")
	}
	e = NewTTransportExceptionFromError(te)
	if isTimeoutError(e) {
		t.Error("isTimeoutError on wrapped TTransportException expected false, got true")
	}

	err := errors.New("foo")
	if isTimeoutError(err) {
		t.Error("isTimeoutError expected false, got true")
	}
	e = NewTTransportExceptionFromError(err)
	if isTimeoutError(e) {
		t.Error("isTimeoutError on wrapped TTransportException expected false, got true")
	}
}
