// Copyright 2015 The Vanadium 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 xunit contains types and functions for manipulating xunit
// files.
package xunit

import (
	"bytes"
	"encoding/xml"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
	"time"

	"v.io/jiri"
	"v.io/x/devtools/tooldata"
)

type TestSuites struct {
	Suites  []TestSuite `xml:"testsuite"`
	XMLName xml.Name    `xml:"testsuites"`
}

type TestSuite struct {
	Name     string     `xml:"name,attr"`
	Cases    []TestCase `xml:"testcase"`
	Errors   int        `xml:"errors,attr"`
	Failures int        `xml:"failures,attr"`
	Skip     int        `xml:"skip,attr"`
	Tests    int        `xml:"tests,attr"`
}

type TestCase struct {
	Name      string    `xml:"name,attr"`
	Classname string    `xml:"classname,attr"`
	Errors    []Error   `xml:"error"`
	Failures  []Failure `xml:"failure"`
	Time      string    `xml:"time,attr"`
	Skipped   []string  `xml:"skipped"`
}

type Error struct {
	Message string `xml:"message,attr"`
	Data    string `xml:",chardata"`
}

type Failure struct {
	Message string `xml:"message,attr"`
	Data    string `xml:",chardata"`
}

// CreateReport generates an xUnit report using the given test suites.
func CreateReport(jirix *jiri.X, testName string, suites []TestSuite) error {
	result := TestSuites{Suites: suites}
	bytes, err := xml.MarshalIndent(result, "", "  ")
	if err != nil {
		return fmt.Errorf("MarshalIndent(%v) failed: %v", result, err)
	}
	if err := jirix.NewSeq().WriteFile(ReportPath(testName), bytes, os.FileMode(0644)).Done(); err != nil {
		return fmt.Errorf("WriteFile(%v) failed: %v", ReportPath(testName), err)
	}
	return nil
}

// CreateTestSuiteWithFailure encodes the given information as a test
// suite with a single failure.
func CreateTestSuiteWithFailure(pkgName, testName, failureMessage, failureOutput string, duration time.Duration) *TestSuite {
	s := TestSuite{Name: pkgName}
	c := TestCase{
		Classname: pkgName,
		Name:      testName,
		Time:      fmt.Sprintf("%.2f", duration.Seconds()),
	}
	s.Tests = 1
	f := Failure{
		Message: failureMessage,
		Data:    failureOutput,
	}
	c.Failures = append(c.Failures, f)
	s.Failures = 1
	s.Cases = append(s.Cases, c)
	return &s
}

// CreateFailureReport creates an xUnit report for the given failure.
func CreateFailureReport(jirix *jiri.X, testName, pkgName, testCaseName, failureMessage, failureOutput string) error {
	s := CreateTestSuiteWithFailure(pkgName, testCaseName, failureMessage, failureOutput, 0)
	if err := CreateReport(jirix, testName, []TestSuite{*s}); err != nil {
		return err
	}
	return nil
}

// ReportPath returns the path to the xUnit file.
//
// TODO(jsimsa): Once all Jenkins shell test scripts are ported to Go,
// change the filename to xunit_report_<testName>.xml.
func ReportPath(testName string) string {
	workspace, fileName := os.Getenv("WORKSPACE"), fmt.Sprintf("tests_%s.xml", strings.Replace(testName, "-", "_", -1))
	if workspace == "" {
		return filepath.Join(os.Getenv("HOME"), "tmp", testName, fileName)
	} else {
		return filepath.Join(workspace, fileName)
	}
}

// TestSuitesFromGoTestOutput reads data from the given input, assuming
// it contains test results generated by "go test -v", and returns it
// as an in-memory data structure.
func TestSuitesFromGoTestOutput(jirix *jiri.X, testOutput io.Reader) ([]*TestSuite, error) {
	bin, err := tooldata.ThirdPartyBinPath(jirix, "go2xunit")
	if err != nil {
		return nil, err
	}
	var out bytes.Buffer
	if err := jirix.NewSeq().Read(testOutput).Capture(&out, nil).Last(bin); err != nil {
		return nil, err
	}
	var suite TestSuite
	if err := xml.Unmarshal(out.Bytes(), &suite); err != nil {
		return nil, fmt.Errorf("Unmarshal() failed: %v\n%v", err, out.String())
	}
	if suite.Tests > 0 {
		return []*TestSuite{&suite}, nil
	}
	// go2xunit has most likely output multiple testsuites i.e.
	// <testsuites>
	//   <testsuite>
	//   </testsuite>
	//   <testsuite>
	//   </testsuite>
	// </testsuites>
	// which results in zero tests if Unmarshal is called expecting a single
	// testsuite. This seems to happen when a test itself invokes a test.
	var suites TestSuites
	if err := xml.Unmarshal(out.Bytes(), &suites); err != nil {
		if !strings.Contains(err.Error(), "expected element type <testsuites> but have <testsuite>") {
			return nil, fmt.Errorf("Unmarshal() failed: %v\n%v", err, out.String())
		}
	}
	if len(suites.Suites) == 0 {
		return []*TestSuite{&suite}, nil
	}
	rc := make([]*TestSuite, len(suites.Suites), len(suites.Suites))
	for i, _ := range suites.Suites {
		rc[i] = &suites.Suites[i]
	}
	return rc, nil
}
