Skip to content

Commit

Permalink
add CheckSemVer unit test
Browse files Browse the repository at this point in the history
Signed-off-by: liang chenye <liangchenye@huawei.com>
  • Loading branch information
liangchenye committed Sep 8, 2016
1 parent 66950fa commit 06163fe
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 54 deletions.
35 changes: 2 additions & 33 deletions cmd/ocitools/validate.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
package main

import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path"
"strings"
"unicode/utf8"

rspec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/urfave/cli"

"github.com/opencontainers/ocitools/validate"
Expand All @@ -26,37 +20,12 @@ var bundleValidateCommand = cli.Command{
Before: before,
Action: func(context *cli.Context) error {
inputPath := context.String("path")
if inputPath == "" {
return fmt.Errorf("Bundle path shouldn't be empty")
}

if _, err := os.Stat(inputPath); err != nil {
return err
}

configPath := path.Join(inputPath, "config.json")
content, err := ioutil.ReadFile(configPath)
hostSpecific := context.GlobalBool("host-specific")
v, err := validate.NewValidatorFromPath(inputPath, hostSpecific)
if err != nil {
return err
}
if !utf8.Valid(content) {
return fmt.Errorf("%q is not encoded in UTF-8", configPath)
}
var spec rspec.Spec
if err = json.Unmarshal(content, &spec); err != nil {
return err
}

rootfsPath := path.Join(inputPath, spec.Root.Path)
if fi, err := os.Stat(rootfsPath); err != nil {
return fmt.Errorf("Cannot find the root path %q", rootfsPath)
} else if !fi.IsDir() {
return fmt.Errorf("The root path %q is not a directory.", rootfsPath)
}

hostSpecific := context.GlobalBool("host-specific")

v := validate.NewValidator(spec, rootfsPath, hostSpecific)
errMsgs := v.CheckAll()
if len(errMsgs) > 0 {
return fmt.Errorf("%d Errors detected:\n%s", len(errMsgs), strings.Join(errMsgs, "\n"))
Expand Down
85 changes: 64 additions & 21 deletions validate/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ package validate

import (
"bufio"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"reflect"
"strings"
"unicode"
"unicode/utf8"

"github.com/Sirupsen/logrus"
"github.com/blang/semver"
Expand Down Expand Up @@ -53,16 +56,42 @@ var (
)

type Validator struct {
spec rspec.Spec
rootfs string
hostSpecific bool
spec *rspec.Spec
bundlePath string
HostSpecific bool
}

func NewValidator(spec rspec.Spec, rootfs string, hostSpecific bool) Validator {
return Validator{spec: spec, rootfs: rootfs, hostSpecific: hostSpecific}
func NewValidator(spec *rspec.Spec, bundlePath string, hostSpecific bool) Validator {
return Validator{spec: spec, bundlePath: bundlePath, HostSpecific: hostSpecific}
}

func NewValidatorFromPath(bundlePath string, hostSpecific bool) (Validator, error) {
if bundlePath == "" {
return Validator{}, fmt.Errorf("Bundle path shouldn't be empty")
}

if _, err := os.Stat(bundlePath); err != nil {
return Validator{}, err
}

configPath := path.Join(bundlePath, "config.json")
content, err := ioutil.ReadFile(configPath)
if err != nil {
return Validator{}, err
}
if !utf8.Valid(content) {
return Validator{}, fmt.Errorf("%q is not encoded in UTF-8", configPath)
}
var spec rspec.Spec
if err = json.Unmarshal(content, &spec); err != nil {
return Validator{}, err
}

return NewValidator(&spec, bundlePath, hostSpecific), nil
}

func (v *Validator) CheckAll() (msgs []string) {
msgs = append(msgs, v.CheckRootfsPath()...)
msgs = append(msgs, v.CheckMandatoryFields()...)
msgs = append(msgs, v.CheckSemVer()...)
msgs = append(msgs, v.CheckMounts()...)
Expand All @@ -74,6 +103,19 @@ func (v *Validator) CheckAll() (msgs []string) {
return
}

func (v *Validator) CheckRootfsPath() (msgs []string) {
logrus.Debugf("check rootfs path")

rootfsPath := path.Join(v.bundlePath, v.spec.Root.Path)
if fi, err := os.Stat(rootfsPath); err != nil {
msgs = append(msgs, fmt.Sprintf("Cannot find the root path %q", rootfsPath))
} else if !fi.IsDir() {
msgs = append(msgs, fmt.Sprintf("The root path %q is not a directory.", rootfsPath))
}

return

}
func (v *Validator) CheckSemVer() (msgs []string) {
logrus.Debugf("check semver")

Expand Down Expand Up @@ -118,6 +160,16 @@ func (v *Validator) CheckPlatform() (msgs []string) {
return
}

func (v *Validator) CheckHooks() (msgs []string) {
logrus.Debugf("check hooks")

msgs = append(msgs, checkEventHooks("pre-start", v.spec.Hooks.Prestart, v.HostSpecific)...)
msgs = append(msgs, checkEventHooks("post-start", v.spec.Hooks.Poststart, v.HostSpecific)...)
msgs = append(msgs, checkEventHooks("post-stop", v.spec.Hooks.Poststop, v.HostSpecific)...)

return
}

func checkEventHooks(hookType string, hooks []rspec.Hook, hostSpecific bool) (msgs []string) {
for _, hook := range hooks {
if !filepath.IsAbs(hook.Path) {
Expand All @@ -143,15 +195,6 @@ func checkEventHooks(hookType string, hooks []rspec.Hook, hostSpecific bool) (ms

return
}
func (v *Validator) CheckHooks() (msgs []string) {
logrus.Debugf("check hooks")

msgs = append(msgs, checkEventHooks("pre-start", v.spec.Hooks.Prestart, v.hostSpecific)...)
msgs = append(msgs, checkEventHooks("post-start", v.spec.Hooks.Poststart, v.hostSpecific)...)
msgs = append(msgs, checkEventHooks("post-stop", v.spec.Hooks.Poststop, v.hostSpecific)...)

return
}

func (v *Validator) CheckProcess() (msgs []string) {
logrus.Debugf("check process")
Expand Down Expand Up @@ -181,7 +224,7 @@ func (v *Validator) CheckProcess() (msgs []string) {
}

if len(process.ApparmorProfile) > 0 {
profilePath := filepath.Join(v.rootfs, "/etc/apparmor.d", process.ApparmorProfile)
profilePath := filepath.Join(v.bundlePath, v.spec.Root.Path, "/etc/apparmor.d", process.ApparmorProfile)
_, err := os.Stat(profilePath)
if err != nil {
msgs = append(msgs, err.Error())
Expand All @@ -195,7 +238,7 @@ func supportedMountTypes(OS string, hostSpecific bool) (map[string]bool, error)
supportedTypes := make(map[string]bool)

if OS != "linux" && OS != "windows" {
logrus.Warnf("%v is not supported to (v *Validator) Check mount type", OS)
logrus.Warnf("%v is not supported to check mount type", OS)
return nil, nil
} else if OS == "windows" {
supportedTypes["ntfs"] = true
Expand Down Expand Up @@ -235,7 +278,7 @@ func supportedMountTypes(OS string, hostSpecific bool) (map[string]bool, error)
func (v *Validator) CheckMounts() (msgs []string) {
logrus.Debugf("check mounts")

supportedTypes, err := supportedMountTypes(v.spec.Platform.OS, v.hostSpecific)
supportedTypes, err := supportedMountTypes(v.spec.Platform.OS, v.HostSpecific)
if err != nil {
msgs = append(msgs, err.Error())
return
Expand Down Expand Up @@ -310,12 +353,12 @@ func (v *Validator) CheckLinux() (msgs []string) {
}

if v.spec.Linux.Resources != nil {
ms := v.checkLinuxResources()
ms := v.CheckLinuxResources()
msgs = append(msgs, ms...)
}

if v.spec.Linux.Seccomp != nil {
ms := v.checkSeccomp()
ms := v.CheckSeccomp()
msgs = append(msgs, ms...)
}

Expand All @@ -334,7 +377,7 @@ func (v *Validator) CheckLinux() (msgs []string) {
return
}

func (v *Validator) checkLinuxResources() (msgs []string) {
func (v *Validator) CheckLinuxResources() (msgs []string) {
logrus.Debugf("check linux resources")

r := v.spec.Linux.Resources
Expand All @@ -350,7 +393,7 @@ func (v *Validator) checkLinuxResources() (msgs []string) {
return
}

func (v *Validator) checkSeccomp() (msgs []string) {
func (v *Validator) CheckSeccomp() (msgs []string) {
logrus.Debugf("check linux seccomp")

s := v.spec.Linux.Seccomp
Expand Down
33 changes: 33 additions & 0 deletions validate/validate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package validate

import (
"strings"
"testing"

rspec "github.com/opencontainers/runtime-spec/specs-go"
)

func checkErrors(t *testing.T, title string, msgs []string, valid bool) {
if valid && len(msgs) > 0 {
t.Fatalf("%s: expected not to get error, but get %d errors:\n%s", title, len(msgs), strings.Join(msgs, "\n"))
} else if !valid && len(msgs) == 0 {
t.Fatalf("%s: expected to get error, but actually not", title)
}
}

func TestCheckSemVer(t *testing.T) {
cases := []struct {
val string
expected bool
}{
{rspec.Version, true},
//FIXME: validate currently only handles rpsec.Version
{"0.0.1", false},
{"invalid", false},
}

for _, c := range cases {
v := NewValidator(&rspec.Spec{Version: c.val}, "", false)
checkErrors(t, "checkSemVer "+c.val, v.CheckSemVer(), c.expected)
}
}

0 comments on commit 06163fe

Please sign in to comment.