Skip to content
This repository has been archived by the owner on Feb 27, 2020. It is now read-only.

Commit

Permalink
A few more abstractions and a test case definitions... tests still to…
Browse files Browse the repository at this point in the history
… done
  • Loading branch information
jonasfj committed Jan 29, 2016
1 parent cd1794d commit f8d25f9
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 1 deletion.
18 changes: 18 additions & 0 deletions engines/enginetest/artifacts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package enginetest

// The ArtifactTestCase contains information sufficient to test artifact
// extration from an engine.
type ArtifactTestCase struct {
Engine string
// Path of a file containing the string "Hello World"
HelloWorldFilePath string
// Path to a file that doesn't exist, and will return ErrResourceNotFound
FileNotFoundPath string
// Path to a folder that doesn't exist, and will return ErrResourceNotFound
FolderNotFoundPath string
// Path to a folder that contains: A.txt, B.txt and C/C.txt, each containing
// the string "Hello World"
NestedFolderPath string
// Payload that will generate a ResultSet containing paths described above.
Payload string
}
13 changes: 13 additions & 0 deletions engines/enginetest/environmentvariable.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package enginetest

// The EnvVarTestCase contains information sufficient to setting an environment
// variable.
type EnvVarTestCase struct {
Engine string
// Valid name for an environment variable.
VariableName string
// Invalid environment variable name.
InvalidVariableName string
// Payload that will print the value of VariableName to the log.
Payload string
}
33 changes: 33 additions & 0 deletions engines/enginetest/interactive.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package enginetest

import "github.com/taskcluster/taskcluster-worker/engines"

// The ShellTestCase contains information sufficient to test the interactive
// shell provided by a Sandbox
type ShellTestCase struct {
Engine string
// Command to pipe to the Shell over stdin
Command string
// Result to expect from the Shell on stdout
Stdout string
// Result to expect from the Shell on stderr
Stderr string
// Payload for the engine that will contain an interactive environment as
// described above.
Payload string
}

// The DisplayTestCase contains information sufficient to test the interactive
// display provided by a Sandbox
type DisplayTestCase struct {
Engine string
// List of display that should be returned from Sandbox.ListDisplays(),
// They will all be opened to ensure that they are in fact VNC connections.
Displays []engines.Display
// Name of a display that does not exist, it will be attempted opened to
// check that this failure is handled gracefully.
InvalidDisplayName string
// Payload for the engine that will contain an interactive environment as
// described above.
Payload string
}
3 changes: 3 additions & 0 deletions engines/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ var ErrSandboxAborted = errors.New("Exection of sandbox was aborted")
// ErrNoSuchDisplay is used to indicate that a requested display doesn't exist.
var ErrNoSuchDisplay = errors.New("No such display exists")

// ErrNamingConflict is used to indicate that a name is already in use.
var ErrNamingConflict = errors.New("Conflicting name is already in use")

// ErrNonFatalInternalError is used to indicate that the operation failed
// because of internal error that isn't expected to affect other tasks.
var ErrNonFatalInternalError = errors.New("Engine encountered a non-fatal internal error")
Expand Down
47 changes: 47 additions & 0 deletions engines/mock/mocksandbox.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package mockengine

import (
"bytes"
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
"net/url"
"strings"
"sync"
"time"

Expand All @@ -29,6 +33,7 @@ type sandbox struct {
context *runtime.TaskContext
mounts map[string]*mount
proxies map[string]http.Handler
files map[string][]byte
result bool
}

Expand Down Expand Up @@ -124,6 +129,12 @@ var functions = map[string]func(*sandbox, string) bool{
s.context.Log(arg)
return false
},
"write-files": func(s *sandbox, arg string) bool {
for _, path := range strings.Split(arg, " ") {
s.files[path] = []byte("Hello World")
}
return true
},
}

func (s *sandbox) WaitForResult() (engines.ResultSet, error) {
Expand All @@ -141,6 +152,42 @@ func (s *sandbox) WaitForResult() (engines.ResultSet, error) {
return s, nil
}

func (s *sandbox) ExtractFile(path string) (io.ReadCloser, error) {
data := s.files[path]
if data == nil {
return nil, engines.ErrResourceNotFound
}
return ioutil.NopCloser(bytes.NewBuffer(data)), nil
}

func (s *sandbox) ExtractFolder(folder string, handler engines.FileHandler) error {
if !strings.HasSuffix(folder, "/") {
folder += "/"
}
wg := sync.WaitGroup{}
foundFolder := false
for path, data := range s.files {
if strings.HasPrefix(path, folder) {
foundFolder = true
if path == folder {
// In this engine a filename ending with / is a folder, and its content
// is ignored, it's only used as indicator of folder existence
continue
}
wg.Add(1)
go func(path string, data []byte) {
handler(path, ioutil.NopCloser(bytes.NewBuffer(data)))
wg.Done()
}(path, data)
}
}
wg.Done()
if !foundFolder {
return engines.ErrResourceNotFound
}
return nil
}

///////////////////////////// Implementation of ResultSet interface

func (s *sandbox) Success() bool {
Expand Down
22 changes: 21 additions & 1 deletion engines/sandboxbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ type SandboxBuilder interface {
// respectively.
//
// Non-fatal errors: MalformedPayloadError, ErrMutableMountNotSupported,
// ErrImmutableMountNotSupported, ErrFeatureNotSupported.
// ErrImmutableMountNotSupported, ErrFeatureNotSupported, ErrNamingConflict
AttachVolume(mountpoint string, volume Volume, readOnly bool) error

// Attach a proxy to the sandbox.
Expand All @@ -58,8 +58,22 @@ type SandboxBuilder interface {
// ErrFeatureNotSupported.
//
// Non-fatal errors: MalformedPayloadError, ErrFeatureNotSupported,
// ErrNamingConflict
AttachProxy(hostname string, handler http.Handler) error

// Set an environement variable.
//
// If the format of the environment variable name is invalid this method
// should return a MalformedPayloadError with explaining why the name is
// invalid.
//
// If the environment variable have previously been declared, this method
// must return ErrNamingConflict.
//
// Non-fatal errors: ErrFeatureNotSupported, MalformedPayloadError,
// ErrNamingConflict
SetEnvironmentVariable(name string, value string) error

// Start execution of task in sandbox. After a call to this method resources
// held by the SandboxBuilder instance should be released or transferred to
// the Sandbox implementation.
Expand Down Expand Up @@ -94,6 +108,12 @@ func (SandboxBuilderBase) AttachProxy(string, http.Handler) error {
return ErrFeatureNotSupported
}

// SetEnvironmentVariable return ErrFeatureNotSupported indicating that the
// feature isn't supported.
func (SandboxBuilderBase) SetEnvironmentVariable(string, string) error {
return ErrFeatureNotSupported
}

// Discard returns nil, indicating that resources have been released.
func (SandboxBuilderBase) Discard() error {
return nil
Expand Down

0 comments on commit f8d25f9

Please sign in to comment.