1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Contributor:
// - Aaron Meihm ameihm@mozilla.com
package scribe
import (
"fmt"
)
// Document describes a scribe document; a document contains all tests and other
// infomration used to execute a policy check
type Document struct {
Variables []Variable `json:"variables,omitempty" yaml:"variables,omitempty"`
Objects []Object `json:"objects,omitempty" yaml:"objects,omitempty"`
Tests []Test `json:"tests,omitempty" yaml:"tests,omitempty"`
}
// Validate a scribe document for consistency. This identifies any errors in
// the document that are not JSON syntax related, including missing fields or
// references to tests that do not exist. Returns an error if validation fails.
func (d *Document) Validate() error {
for i := range d.Objects {
err := d.Objects[i].validate(d)
if err != nil {
return err
}
}
for i := range d.Tests {
err := d.Tests[i].validate(d)
if err != nil {
return err
}
}
return nil
}
// GetTestIdentifiers returns the test identifiers for all tests present in
// the document.
func (d *Document) GetTestIdentifiers() []string {
ret := make([]string, 0)
for _, x := range d.Tests {
ret = append(ret, x.TestID)
}
return ret
}
func (d *Document) prepareObjects() error {
// Mark any chain objects; these will be skipped during preparation
// as they are dependent on evaluation of the root object. Chain
// objects are objects that contain chain variables; that is they
// cannot be evaluated as they depend on information being passed
// from the previous object in the chain.
for i := range d.Objects {
d.Objects[i].markChain()
}
// Note that prepare() will return an error if something goes wrong
// but we don't propagate this back. Errors within object preparation
// are kept localized to the object, and are not considered fatal to
// execution of the entire document.
for i := range d.Objects {
d.Objects[i].prepare(d)
}
debugPrint("prepareObjects(): firing any import chains\n")
for i := range d.Objects {
d.Objects[i].fireChains(d)
}
return nil
}
func (d *Document) objectPrepared(obj string) (bool, error) {
var objptr *Object
for i := range d.Objects {
if d.Objects[i].Object == obj {
objptr = &d.Objects[i]
}
}
if objptr == nil {
return false, fmt.Errorf("unknown object \"%v\"", obj)
}
// If an error occurred while preparing this object, return that here
// and note preparation as false.
if objptr.err != nil {
return false, objptr.err
}
return objptr.prepared, nil
}
func (d *Document) runTests() error {
// As documented prepareObjects(), we don't propagate errors here but
// instead keep them localized to the test.
for i := range d.Tests {
d.Tests[i].runTest(d)
}
return nil
}
// Return a pointer to a test instance of the test whose identifier matches
func (d *Document) GetTest(testid string) (*Test, error) {
for i := range d.Tests {
if d.Tests[i].TestID == testid {
return &d.Tests[i], nil
}
}
return nil, fmt.Errorf("unknown test \"%v\"", testid)
}
// Given an object name, return a generic source interface for the object.
func (d *Document) getObjectInterface(obj string) (genericSource, error) {
for i := range d.Objects {
if d.Objects[i].Object == obj {
return d.Objects[i].getSourceInterface(), nil
}
}
return nil, fmt.Errorf("unknown object \"%v\"", obj)
}
// Given an object name, return a generic source interface to a copy of the
// object.
func (d *Document) getObjectInterfaceCopy(obj string) (genericSource, error) {
for i := range d.Objects {
if d.Objects[i].Object == obj {
newobj := d.Objects[i]
return newobj.getSourceInterface(), nil
}
}
return nil, fmt.Errorf("unknown object \"%v\"", obj)
}
|