mirror of https://github.com/perkeep/perkeep.git
Merge "integration tests: kill camlistored when all tests are done"
This commit is contained in:
commit
e8d0200a11
|
@ -0,0 +1,34 @@
|
|||
// +build linux darwin
|
||||
|
||||
/*
|
||||
Copyright 2013 The Camlistore Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package fs
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"camlistore.org/pkg/test"
|
||||
)
|
||||
|
||||
// Make sure that the camlistored process started
|
||||
// by the World gets terminated when all the tests
|
||||
// are done.
|
||||
// This works only as long as TestZLastTest is the
|
||||
// last test to run in the package.
|
||||
func TestZLastTest(t *testing.T) {
|
||||
test.GetWorldMaybe(t).Stop()
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
// +build !appengine
|
||||
|
||||
/*
|
||||
Copyright 2013 The Camlistore Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package osutil
|
||||
|
||||
import (
|
||||
"log"
|
||||
)
|
||||
|
||||
func DieOnParentDeath() {
|
||||
// TODO(mpl): maybe the way it's done in findproc_normal.go actually works
|
||||
// on appengine too? Verify that.
|
||||
log.Fatal("DieOnParentDeath not implemented on appengine.")
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
// +build !appengine
|
||||
|
||||
/*
|
||||
Copyright 2013 The Camlistore Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package osutil
|
||||
|
||||
import (
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// DieOnParentDeath starts a goroutine that regularly checks that
|
||||
// the current process can find its parent, and calls os.Exit(0)
|
||||
// as soon as it cannot.
|
||||
func DieOnParentDeath() {
|
||||
// TODO: on Linux, use PR_SET_PDEATHSIG later. For now, the portable way:
|
||||
go func() {
|
||||
pollParent(30 * time.Second)
|
||||
os.Exit(0)
|
||||
}()
|
||||
}
|
||||
|
||||
// pollParent checks every t that the ppid of the current
|
||||
// process has not changed (i.e that the process has not
|
||||
// been orphaned). It returns as soon as that ppid changes.
|
||||
func pollParent(t time.Duration) {
|
||||
for initial := os.Getppid(); initial == os.Getppid(); time.Sleep(t) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
Copyright 2013 The Camlistore Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"camlistore.org/pkg/test"
|
||||
)
|
||||
|
||||
// Make sure that the camlistored process started
|
||||
// by the World gets terminated when all the tests
|
||||
// are done.
|
||||
// This works only as long as TestZLastTest is the
|
||||
// last test to run in the package.
|
||||
func TestZLastTest(t *testing.T) {
|
||||
test.GetWorldMaybe(t).Stop()
|
||||
}
|
|
@ -85,12 +85,12 @@ func (w *World) Start() error {
|
|||
{
|
||||
cmd := exec.Command("go", "run", "make.go")
|
||||
cmd.Dir = w.camRoot
|
||||
log.Printf("Running make.go to build camlistore binaries for testing...")
|
||||
log.Print("Running make.go to build camlistore binaries for testing...")
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error building world: %v, %s", err, string(out))
|
||||
}
|
||||
log.Printf("Ran make.go.")
|
||||
log.Print("Ran make.go.")
|
||||
}
|
||||
|
||||
// Start camlistored.
|
||||
|
@ -99,12 +99,14 @@ func (w *World) Start() error {
|
|||
filepath.Join(w.camRoot, "bin", "camlistored"),
|
||||
"--configfile="+filepath.Join(w.camRoot, "pkg", "test", "testdata", "server-config.json"),
|
||||
"--listen=FD:3",
|
||||
"--pollparent=true",
|
||||
)
|
||||
var buf bytes.Buffer
|
||||
w.server.Stdout = &buf
|
||||
w.server.Stderr = &buf
|
||||
w.server.Dir = w.tempDir
|
||||
w.server.Env = append(os.Environ(),
|
||||
"CAMLI_DEBUG=1",
|
||||
"CAMLI_ROOT="+w.tempDir,
|
||||
"CAMLI_SECRET_RING="+filepath.Join(w.camRoot, filepath.FromSlash("pkg/jsonsign/testdata/test-secring.gpg")),
|
||||
"CAMLI_BASE_URL=http://127.0.0.1:"+strconv.Itoa(w.port),
|
||||
|
@ -146,6 +148,9 @@ func (w *World) Start() error {
|
|||
}
|
||||
|
||||
func (w *World) Stop() {
|
||||
if w == nil {
|
||||
return
|
||||
}
|
||||
w.server.Process.Kill()
|
||||
|
||||
if d := w.tempDir; d != "" {
|
||||
|
@ -153,7 +158,6 @@ func (w *World) Stop() {
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
func (w *World) Cmd(binary string, args ...string) *exec.Cmd {
|
||||
cmd := exec.Command(filepath.Join(w.camRoot, "bin", binary), args...)
|
||||
switch binary {
|
||||
|
@ -199,6 +203,11 @@ func GetWorld(t *testing.T) *World {
|
|||
return w
|
||||
}
|
||||
|
||||
// GetWorldMaybe returns the current World. It might be nil.
|
||||
func GetWorldMaybe(t *testing.T) *World {
|
||||
return theWorld
|
||||
}
|
||||
|
||||
// RunCmd runs c (which is assumed to be something short-lived, like a
|
||||
// camput or camget command), capturing its stdout for return, and
|
||||
// also capturing its stderr, just in the case of errors.
|
||||
|
|
|
@ -35,6 +35,7 @@ import (
|
|||
"os/signal"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
@ -49,11 +50,11 @@ import (
|
|||
// Storage options:
|
||||
_ "camlistore.org/pkg/blobserver/cond"
|
||||
_ "camlistore.org/pkg/blobserver/encrypt"
|
||||
_ "camlistore.org/pkg/blobserver/google"
|
||||
_ "camlistore.org/pkg/blobserver/localdisk"
|
||||
_ "camlistore.org/pkg/blobserver/remote"
|
||||
_ "camlistore.org/pkg/blobserver/replica"
|
||||
_ "camlistore.org/pkg/blobserver/s3"
|
||||
_ "camlistore.org/pkg/blobserver/google"
|
||||
_ "camlistore.org/pkg/blobserver/shard"
|
||||
// Indexers: (also present themselves as storage targets)
|
||||
_ "camlistore.org/pkg/index" // base indexer + in-memory dev index
|
||||
|
@ -76,9 +77,16 @@ var (
|
|||
flagVersion = flag.Bool("version", false, "show version")
|
||||
flagConfigFile = flag.String("configfile", "",
|
||||
"Config file to use, relative to the Camlistore configuration directory root. If blank, the default is used or auto-generated.")
|
||||
listenFlag = flag.String("listen", "", "host:port to listen on, or :0 to auto-select. If blank, the value in the config will be used instead.")
|
||||
listenFlag = flag.String("listen", "", "host:port to listen on, or :0 to auto-select. If blank, the value in the config will be used instead.")
|
||||
flagPollParent bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
if debug, _ := strconv.ParseBool(os.Getenv("CAMLI_DEBUG")); debug {
|
||||
flag.BoolVar(&flagPollParent, "pollparent", false, "Camlistored regularly polls its parent process to detect if it has been orphaned, and terminates in that case. Mainly useful for tests.")
|
||||
}
|
||||
}
|
||||
|
||||
func exitf(pattern string, args ...interface{}) {
|
||||
if !strings.HasSuffix(pattern, "\n") {
|
||||
pattern = pattern + "\n"
|
||||
|
@ -424,5 +432,8 @@ func main() {
|
|||
|
||||
go ws.Serve()
|
||||
go handleSignals()
|
||||
if flagPollParent {
|
||||
osutil.DieOnParentDeath()
|
||||
}
|
||||
select {}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue