// 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 vlog_test

import (
	"bufio"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"testing"

	"v.io/x/lib/vlog"
)

func ExampleConfigure() {
	vlog.Configure()
}

func ExampleInfo() {
	vlog.Info("hello")
}

func ExampleError() {
	vlog.Errorf("%s", "error")
	if vlog.V(2) {
		vlog.Info("some spammy message")
	}
	vlog.VI(2).Infof("another spammy message")
}

func readLogFiles(dir string) ([]string, error) {
	files, err := ioutil.ReadDir(dir)
	if err != nil {
		return nil, err
	}
	var contents []string
	for _, fi := range files {
		// Skip symlinks to avoid double-counting log lines.
		if !fi.Mode().IsRegular() {
			continue
		}
		file, err := os.Open(filepath.Join(dir, fi.Name()))
		if err != nil {
			return nil, err
		}
		scanner := bufio.NewScanner(file)
		for scanner.Scan() {
			if line := scanner.Text(); len(line) > 0 && line[0] == 'I' {
				contents = append(contents, line)
			}
		}
	}
	return contents, nil
}

func TestHeaders(t *testing.T) {
	dir, err := ioutil.TempDir("", "logtest")
	defer os.RemoveAll(dir)
	if err != nil {
		t.Fatalf("unexpected error: %s", err)
	}
	logger := vlog.NewLogger("testHeader")
	logger.Configure(vlog.LogDir(dir), vlog.Level(2))
	logger.Infof("abc\n")
	logger.Infof("wombats\n")
	logger.VI(1).Infof("wombats again\n")
	logger.FlushLog()
	contents, err := readLogFiles(dir)
	if err != nil {
		t.Fatalf("unexpected error: %s", err)
	}
	fileRE := regexp.MustCompile(`\S+ \S+\s+\S+ (.*):.*`)
	for _, line := range contents {
		name := fileRE.FindStringSubmatch(line)
		if len(name) < 2 {
			t.Errorf("failed to find file in %s", line)
			continue
		}
		if name[1] != "log_test.go" {
			t.Errorf("unexpected file name: %s", name[1])
			continue
		}
	}
	if want, got := 3, len(contents); want != got {
		t.Errorf("Expected %d info lines, got %d instead", want, got)
	}
}

func TestDepth(t *testing.T) {
	dir, err := ioutil.TempDir("", "logtest")
	defer os.RemoveAll(dir)
	if err != nil {
		t.Fatalf("unexpected error: %s", err)
	}
	logger := vlog.NewLogger("testHeader")
	logger.Configure(vlog.LogDir(dir), vlog.Level(2))

	logger.InfoDepth(0, "here\n")
	tmp := func() {
		logger.InfoDepth(1, "still here\n")
		logger.InfoDepth(2, "not here\n")
	}
	tmp()
	logger.FlushLog()
	contents, err := readLogFiles(dir)
	if err != nil {
		t.Fatalf("unexpected error: %s", err)
	}
	fileRE := regexp.MustCompile(`\S+ \S+\s+\S+ (.*):.*`)
	files := []string{}
	for _, line := range contents {
		name := fileRE.FindStringSubmatch(line)
		if len(name) < 2 {
			t.Errorf("failed to find file in %s", line)
			continue
		}
		files = append(files, name[1])
	}
	for i, want := range []string{"log_test.go", "log_test.go", "testing.go"} {
		if got := files[i]; got != want {
			t.Errorf("%d: got %v, want %v", i, got, want)
		}
	}
}

func myLoggedFunc() {
	f := vlog.LogCall("entry")
	f("exit")
}

func TestLogCall(t *testing.T) {
	dir, err := ioutil.TempDir("", "logtest")
	defer os.RemoveAll(dir)
	if err != nil {
		t.Fatalf("unexpected error: %s", err)
	}
	logger := vlog.NewLogger("testHeader")
	logger.Configure(vlog.LogDir(dir), vlog.Level(2))
	saveLog := vlog.Log
	defer vlog.SetLog(saveLog)
	vlog.SetLog(logger)

	myLoggedFunc()
	vlog.FlushLog()
	contents, err := readLogFiles(dir)
	if err != nil {
		t.Fatalf("unexpected error: %s", err)
	}
	logCallLineRE := regexp.MustCompile(`\S+ \S+\s+\S+ ([^:]*):.*(call|return)\[(\S*)`)
	for _, line := range contents {
		match := logCallLineRE.FindStringSubmatch(line)
		if len(match) != 4 {
			t.Errorf("failed to match %s", line)
			continue
		}
		fileName, callType, funcName := match[1], match[2], match[3]
		if fileName != "log_test.go" {
			t.Errorf("unexpected file name: %s", fileName)
			continue
		}
		if callType != "call" && callType != "return" {
			t.Errorf("unexpected call type: %s", callType)
		}
		if funcName != "vlog_test.myLoggedFunc" {
			t.Errorf("unexpected func name: %s", funcName)
		}
	}
	if want, got := 2, len(contents); want != got {
		t.Errorf("Expected %d info lines, got %d instead", want, got)
	}
}

func TestVModule(t *testing.T) {
	dir, err := ioutil.TempDir("", "logtest")
	defer os.RemoveAll(dir)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	logger := vlog.NewLogger("testVmodule")
	logger.Configure(vlog.LogDir(dir))
	if logger.V(2) || logger.V(3) {
		t.Errorf("Logging should not be enabled at levels 2 & 3")
	}
	spec := vlog.ModuleSpec{}
	if err := spec.Set("*log_test=2"); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if err := logger.Configure(vlog.OverridePriorConfiguration(true), spec); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !logger.V(2) {
		t.Errorf("logger.V(2) should be true")
	}
	if logger.V(3) {
		t.Errorf("logger.V(3) should be false")
	}
	if vlog.V(2) || vlog.V(3) {
		t.Errorf("Logging should not be enabled at levels 2 & 3")
	}
	vlog.Log.Configure(vlog.OverridePriorConfiguration(true), spec)
	if !vlog.V(2) {
		t.Errorf("vlog.V(2) should be true")
	}
	if vlog.V(3) {
		t.Errorf("vlog.V(3) should be false")
	}
	if vlog.VI(2) != vlog.Log {
		t.Errorf("vlog.V(2) should be vlog.Log")
	}
	if vlog.VI(3) == vlog.Log {
		t.Errorf("vlog.V(3) should not be vlog.Log")
	}
	spec = vlog.ModuleSpec{}
	spec.Set("notlikelytobeinuse=2")
	vlog.Log.Configure(vlog.OverridePriorConfiguration(true), spec)
}

func TestVFilepath(t *testing.T) {
	dir, err := ioutil.TempDir("", "logtest")
	defer os.RemoveAll(dir)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	logger := vlog.NewLogger("testVmodule")
	logger.Configure(vlog.LogDir(dir))
	if logger.V(2) || logger.V(3) {
		t.Errorf("Logging should not be enabled at levels 2 & 3")
	}
	spec := vlog.FilepathSpec{}
	if err := spec.Set(".*log_test=2"); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if err := logger.Configure(vlog.OverridePriorConfiguration(true), spec); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	if !logger.V(2) {
		t.Errorf("logger.V(2) should be true")
	}
	if logger.V(3) {
		t.Errorf("logger.V(3) should be false")
	}
	if vlog.V(2) || vlog.V(3) {
		t.Errorf("Logging should not be enabled at levels 2 & 3")
	}
	vlog.Log.Configure(vlog.OverridePriorConfiguration(true), spec)
	if !vlog.V(2) {
		t.Errorf("vlog.V(2) should be true")
	}
	if vlog.V(3) {
		t.Errorf("vlog.V(3) should be false")
	}
	if vlog.VI(2) != vlog.Log {
		t.Errorf("vlog.V(2) should be vlog.Log")
	}
	if vlog.VI(3) == vlog.Log {
		t.Errorf("vlog.V(3) should not be vlog.Log")
	}
	spec = vlog.FilepathSpec{}
	spec.Set("notlikelytobeinuse=2")
	vlog.Log.Configure(vlog.OverridePriorConfiguration(true), spec)
}

func TestConfigure(t *testing.T) {
	dir, err := ioutil.TempDir("", "logtest")
	defer os.RemoveAll(dir)
	if err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
	logger := vlog.NewLogger("testVmodule")
	if got, want := logger.Configure(vlog.LogDir(dir), vlog.AlsoLogToStderr(false)), error(nil); got != want {
		t.Fatalf("got %v, want %v", got, want)
	}
	if got, want := logger.Configure(vlog.AlsoLogToStderr(true)), vlog.ErrConfigured; got != want {
		t.Fatalf("got %v, want %v", got, want)
	}
	if got, want := logger.Configure(vlog.OverridePriorConfiguration(true), vlog.AlsoLogToStderr(false)), error(nil); got != want {
		t.Fatalf("got %v, want %v", got, want)
	}
}
