// Copyright 2019 Google Inc. All rights reserved.
//
// Licensed 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.

// This executable runs a series of build commands to test and benchmark some critical user journeys.
package main

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"android/soong/ui/build"
	"android/soong/ui/logger"
	"android/soong/ui/metrics"
	"android/soong/ui/status"
	"android/soong/ui/terminal"
	"android/soong/ui/tracer"
)

type Test struct {
	name   string
	args   []string
	before func() error

	results TestResults
}

type TestResults struct {
	metrics *metrics.Metrics
	err     error
}

// Run runs a single build command.  It emulates the "m" command line by calling into Soong UI directly.
func (t *Test) Run(logsDir string) {
	output := terminal.NewStatusOutput(os.Stdout, "", false, false)

	log := logger.New(output)
	defer log.Cleanup()

	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()

	trace := tracer.New(log)
	defer trace.Close()

	met := metrics.New()

	stat := &status.Status{}
	defer stat.Finish()
	stat.AddOutput(output)
	stat.AddOutput(trace.StatusTracer())

	build.SetupSignals(log, cancel, func() {
		trace.Close()
		log.Cleanup()
		stat.Finish()
	})

	buildCtx := build.Context{ContextImpl: &build.ContextImpl{
		Context: ctx,
		Logger:  log,
		Metrics: met,
		Tracer:  trace,
		Writer:  output,
		Status:  stat,
	}}

	defer logger.Recover(func(err error) {
		t.results.err = err
	})

	config := build.NewConfig(buildCtx, t.args...)
	build.SetupOutDir(buildCtx, config)

	os.MkdirAll(logsDir, 0777)
	log.SetOutput(filepath.Join(logsDir, "soong.log"))
	trace.SetOutput(filepath.Join(logsDir, "build.trace"))
	stat.AddOutput(status.NewVerboseLog(log, filepath.Join(logsDir, "verbose.log")))
	stat.AddOutput(status.NewErrorLog(log, filepath.Join(logsDir, "error.log")))
	stat.AddOutput(status.NewProtoErrorLog(log, filepath.Join(logsDir, "build_error")))
	stat.AddOutput(status.NewCriticalPath(log))

	defer met.Dump(filepath.Join(logsDir, "soong_metrics"))

	if start, ok := os.LookupEnv("TRACE_BEGIN_SOONG"); ok {
		if !strings.HasSuffix(start, "N") {
			if start_time, err := strconv.ParseUint(start, 10, 64); err == nil {
				log.Verbosef("Took %dms to start up.",
					time.Since(time.Unix(0, int64(start_time))).Nanoseconds()/time.Millisecond.Nanoseconds())
				buildCtx.CompleteTrace(metrics.RunSetupTool, "startup", start_time, uint64(time.Now().UnixNano()))
			}
		}

		if executable, err := os.Executable(); err == nil {
			trace.ImportMicrofactoryLog(filepath.Join(filepath.Dir(executable), "."+filepath.Base(executable)+".trace"))
		}
	}

	f := build.NewSourceFinder(buildCtx, config)
	defer f.Shutdown()
	build.FindSources(buildCtx, config, f)

	build.Build(buildCtx, config)

	t.results.metrics = met
}

// Touch the Intent.java file to cause a rebuild of the frameworks to monitor the
// incremental build speed as mentioned b/152046247. Intent.java file was chosen
// as it is a key component of the framework and is often modified.
func touchIntentFile() error {
	const intentFileName = "frameworks/base/core/java/android/content/Intent.java"
	currentTime := time.Now().Local()
	return os.Chtimes(intentFileName, currentTime, currentTime)
}

func main() {
	outDir := os.Getenv("OUT_DIR")
	if outDir == "" {
		outDir = "out"
	}

	cujDir := filepath.Join(outDir, "cuj_tests")

	// Use a subdirectory for the out directory for the tests to keep them isolated.
	os.Setenv("OUT_DIR", filepath.Join(cujDir, "out"))

	// Each of these tests is run in sequence without resetting the output tree.  The state of the output tree will
	// affect each successive test.  To maintain the validity of the benchmarks across changes, care must be taken
	// to avoid changing the state of the tree when a test is run.  This is most easily accomplished by adding tests
	// at the end.
	tests := []Test{
		{
			// Reset the out directory to get reproducible results.
			name: "clean",
			args: []string{"clean"},
		},
		{
			// Parse the build files.
			name: "nothing",
			args: []string{"nothing"},
		},
		{
			// Parse the build files again to monitor issues like globs rerunning.
			name: "nothing_rebuild",
			args: []string{"nothing"},
		},
		{
			// Parse the build files again, this should always be very short.
			name: "nothing_rebuild_twice",
			args: []string{"nothing"},
		},
		{
			// Build the framework as a common developer task and one that keeps getting longer.
			name: "framework",
			args: []string{"framework"},
		},
		{
			// Build the framework again to make sure it doesn't rebuild anything.
			name: "framework_rebuild",
			args: []string{"framework"},
		},
		{
			// Build the framework again to make sure it doesn't rebuild anything even if it did the second time.
			name: "framework_rebuild_twice",
			args: []string{"framework"},
		},
		{
			// Scenario major_inc_build (b/152046247): tracking build speed of major incremental build.
			name: "major_inc_build_droid",
			args: []string{"droid"},
		},
		{
			name:   "major_inc_build_framework_minus_apex_after_droid_build",
			args:   []string{"framework-minus-apex"},
			before: touchIntentFile,
		},
		{
			name:   "major_inc_build_framework_after_droid_build",
			args:   []string{"framework"},
			before: touchIntentFile,
		},
		{
			name:   "major_inc_build_sync_after_droid_build",
			args:   []string{"sync"},
			before: touchIntentFile,
		},
		{
			name:   "major_inc_build_droid_rebuild",
			args:   []string{"droid"},
			before: touchIntentFile,
		},
		{
			name:   "major_inc_build_update_api_after_droid_rebuild",
			args:   []string{"update-api"},
			before: touchIntentFile,
		},
	}

	cujMetrics := metrics.NewCriticalUserJourneysMetrics()
	defer cujMetrics.Dump(filepath.Join(cujDir, "logs", "cuj_metrics.pb"))

	for i, t := range tests {
		logsSubDir := fmt.Sprintf("%02d_%s", i, t.name)
		logsDir := filepath.Join(cujDir, "logs", logsSubDir)
		if t.before != nil {
			if err := t.before(); err != nil {
				fmt.Printf("error running before function on test %q: %v\n", t.name, err)
				break
			}
		}
		t.Run(logsDir)
		if t.results.err != nil {
			fmt.Printf("error running test %q: %s\n", t.name, t.results.err)
			break
		}
		if t.results.metrics != nil {
			cujMetrics.Add(t.name, t.results.metrics)
		}
	}
}
