blob: 00ec4bf45fcbea08d5fe3e95d5c7e7132f8383c1 [file] [log] [blame]
package swarming
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"path"
"path/filepath"
"strings"
"testing"
"time"
assert "github.com/stretchr/testify/require"
"go.skia.org/infra/go/isolate"
"go.skia.org/infra/go/testutils"
)
const (
TESTDATA_DIR = "testdata"
TEST_ISOLATE = "test.isolate"
TEST_SCRIPT = "test.py"
)
// TestCreateIsolatedGenJSON verifies that an isolated.gen.json with expected
// values is created from the test isolated files.
func TestCreateIsolatedGenJSON(t *testing.T) {
testutils.LargeTest(t)
workDir, err := ioutil.TempDir("", "swarming_work_")
assert.NoError(t, err)
s, err := NewSwarmingClient(context.Background(), workDir, SWARMING_SERVER, isolate.ISOLATE_SERVER_URL_FAKE, "")
assert.NoError(t, err)
defer s.Cleanup()
extraArgs := map[string]string{
"ARG_1": "arg_1",
"ARG_2": "arg_2",
}
blackList := []string{"blacklist1", "blacklist2"}
// Pass in a relative path to isolate file. It should return an err.
genJSON, err := s.CreateIsolatedGenJSON(path.Join(TESTDATA_DIR, TEST_ISOLATE), TESTDATA_DIR, "linux", "testTask1", extraArgs, blackList)
assert.Equal(t, "", genJSON)
assert.NotNil(t, err)
assert.Equal(t, "isolate path testdata/test.isolate must be an absolute path", err.Error())
// Now pass in an absolute path to isolate file. This should succeed.
absTestDataDir, err := filepath.Abs(TESTDATA_DIR)
assert.NoError(t, err)
genJSON, err = s.CreateIsolatedGenJSON(path.Join(absTestDataDir, TEST_ISOLATE), TESTDATA_DIR, "linux", "testTask1", extraArgs, blackList)
assert.NoError(t, err)
contents, err := ioutil.ReadFile(genJSON)
assert.NoError(t, err)
var output struct {
Version int `json:"version"`
Dir string `json:"dir"`
Args []string `json:"args"`
}
err = json.Unmarshal(contents, &output)
assert.NoError(t, err)
assert.Equal(t, 1, output.Version)
assert.Equal(t, TESTDATA_DIR, path.Base(output.Dir))
// Assert the args value. The position of the extra vars is non-deterministic
// because it is in a map.
expectedOutputBeforeExtraVars := []string{
"--isolate", path.Join(absTestDataDir, TEST_ISOLATE),
"--isolated", fmt.Sprintf("%s/testTask1.isolated", s.WorkDir),
"--config-variable", "OS", "linux",
"--blacklist", "blacklist1", "--blacklist", "blacklist2"}
extraVarsPos := len(output.Args) - 6
assert.Equal(t, output.Args[:extraVarsPos], expectedOutputBeforeExtraVars)
assert.Equal(t, 17, len(output.Args))
}
// E2E_Success verifies that an islated.gen.json is created, batcharchive works,
// triggering swarming tasks works and collecting swarming tasks works.
func E2E_Success(t *testing.T) {
// Instantiate the swarming client.
workDir, err := ioutil.TempDir("", "swarming_work_")
assert.NoError(t, err)
s, err := NewSwarmingClient(context.Background(), workDir, SWARMING_SERVER, isolate.ISOLATE_SERVER_URL_FAKE, "")
assert.NoError(t, err)
defer s.Cleanup()
ctx := context.Background()
// Create isolated.gen.json files to pass to batcharchive.
blackList := []string{"blacklist1", "blacklist2"}
absTestDataDir, err := filepath.Abs(TESTDATA_DIR)
assert.NoError(t, err)
taskNames := []string{"testTask1", "testTask2"}
genJSONs := []string{}
for _, taskName := range taskNames {
extraArgs := map[string]string{
"ARG_1": fmt.Sprintf("arg_1_%s", taskName),
"ARG_2": fmt.Sprintf("arg_2_%s", taskName),
}
genJSON, err := s.CreateIsolatedGenJSON(path.Join(absTestDataDir, TEST_ISOLATE), s.WorkDir, "linux", taskName, extraArgs, blackList)
assert.NoError(t, err)
genJSONs = append(genJSONs, genJSON)
}
// Batcharchive the task.
tasksToHashes, err := s.BatchArchiveTargets(ctx, genJSONs, 5*time.Minute)
assert.NoError(t, err)
assert.Equal(t, 2, len(tasksToHashes))
for _, taskName := range taskNames {
hash, exists := tasksToHashes[taskName]
assert.True(t, exists)
assert.NotNil(t, hash)
}
// Trigger swarming using the isolate hashes.
dimensions := map[string]string{"pool": "Chrome"}
tags := map[string]string{"testing": "123"}
tasks, err := s.TriggerSwarmingTasks(ctx, tasksToHashes, dimensions, tags, []string{}, RECOMMENDED_PRIORITY, RECOMMENDED_EXPIRATION, RECOMMENDED_HARD_TIMEOUT, RECOMMENDED_IO_TIMEOUT, false, true, "")
assert.NoError(t, err)
// Collect both output and file output of all tasks.
for _, task := range tasks {
output, outputDir, err := task.Collect(ctx, s)
assert.NoError(t, err)
output = sanitizeOutput(output)
assert.Equal(t, fmt.Sprintf("arg_1_%s\narg_2_%s\n", task.Title, task.Title), output)
tagsWithTaskName := map[string]string{"testing": "123", "name": task.Title}
assert.Equal(t, tagsWithTaskName, task.Tags)
// Verify contents of the outputDir.
rawFileOutput, err := ioutil.ReadFile(path.Join(outputDir, "output.txt"))
assert.NoError(t, err)
fileOutput := strings.Replace(string(rawFileOutput), "\r\n", "\n", -1)
assert.Equal(t, "testing\ntesting", fileOutput)
}
}
// E2E_OnFailure verifies that an islated.gen.json is created, batcharchive
// works, triggering swarming tasks works and collecting swarming tasks with one
// failure works.
func E2E_OneFailure(t *testing.T) {
// Instantiate the swarming client.
workDir, err := ioutil.TempDir("", "swarming_work_")
assert.NoError(t, err)
ctx := context.Background()
s, err := NewSwarmingClient(ctx, workDir, SWARMING_SERVER, isolate.ISOLATE_SERVER_URL_FAKE, "")
assert.NoError(t, err)
defer s.Cleanup()
// Create isolated.gen.json files to pass to batcharchive.
blackList := []string{"blacklist1", "blacklist2"}
absTestDataDir, err := filepath.Abs(TESTDATA_DIR)
assert.NoError(t, err)
taskNames := []string{"testTask1", "testTask2"}
genJSONs := []string{}
for _, taskName := range taskNames {
extraArgs := map[string]string{
"ARG_1": fmt.Sprintf("arg_1_%s", taskName),
"ARG_2": fmt.Sprintf("arg_2_%s", taskName),
}
// Add an empty 2nd argument for testTask1 to cause a failure.
if taskName == "testTask1" {
extraArgs["ARG_2"] = ""
}
genJSON, err := s.CreateIsolatedGenJSON(path.Join(absTestDataDir, TEST_ISOLATE), s.WorkDir, "linux", taskName, extraArgs, blackList)
assert.NoError(t, err)
genJSONs = append(genJSONs, genJSON)
}
// Batcharchive the task.
tasksToHashes, err := s.BatchArchiveTargets(ctx, genJSONs, 5*time.Minute)
assert.NoError(t, err)
assert.Equal(t, 2, len(tasksToHashes))
for _, taskName := range taskNames {
hash, exists := tasksToHashes[taskName]
assert.True(t, exists)
assert.NotNil(t, hash)
}
// Trigger swarming using the isolate hashes.
dimensions := map[string]string{"pool": "Chrome"}
tags := map[string]string{"testing": "123"}
tasks, err := s.TriggerSwarmingTasks(ctx, tasksToHashes, dimensions, tags, []string{}, RECOMMENDED_PRIORITY, RECOMMENDED_EXPIRATION, RECOMMENDED_HARD_TIMEOUT, RECOMMENDED_IO_TIMEOUT, false, false, "")
assert.NoError(t, err)
// Collect testTask1. It should have failed.
output1, outputDir1, err1 := tasks[0].Collect(ctx, s)
assert.Equal(t, tags, tasks[0].Tags)
output1 = sanitizeOutput(output1)
assert.Equal(t, "", output1)
assert.Equal(t, "", outputDir1)
assert.NotNil(t, err1)
assert.True(t, strings.HasPrefix(err1.Error(), "Swarming trigger for testTask1 failed with: Command exited with exit status 1: "))
// Collect testTask2. It should have succeeded.
output2, outputDir2, err2 := tasks[1].Collect(ctx, s)
assert.NoError(t, err2)
assert.Equal(t, tags, tasks[1].Tags)
output2 = sanitizeOutput(output2)
assert.Equal(t, fmt.Sprintf("arg_1_%s\narg_2_%s\n", tasks[1].Title, tasks[1].Title), output2)
// Verify contents of the outputDir.
rawFileOutput, err := ioutil.ReadFile(path.Join(outputDir2, "output.txt"))
assert.NoError(t, err)
fileOutput := strings.Replace(string(rawFileOutput), "\r\n", "\n", -1)
assert.Equal(t, "testing\ntesting", fileOutput)
}
// sanitizeOutput makes the task output consistent. Sometimes the outputs comes
// back with "\r\n" and sometimes with "\n". This function makes it always be "\n".
func sanitizeOutput(output string) string {
return strings.Replace(output, "\r\n", "\n", -1)
}