172 lines
4.6 KiB
Go
172 lines
4.6 KiB
Go
/*
|
|
Copyright 2020 The Flux 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 test
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
. "github.com/onsi/gomega"
|
|
)
|
|
|
|
// TODO rewrite this as just doing the diff, so I can test that it
|
|
// fails at the right times too.
|
|
func ExpectMatchingDirectories(actualRoot, expectedRoot string) {
|
|
Expect(actualRoot).To(BeADirectory())
|
|
Expect(expectedRoot).To(BeADirectory())
|
|
actualonly, expectedonly, different := DiffDirectories(actualRoot, expectedRoot)
|
|
Expect(actualonly).To(BeEmpty(), "Expect no files in %s but not in %s", actualRoot, expectedRoot)
|
|
Expect(expectedonly).To(BeEmpty(), "Expect no files in %s but not in %s", expectedRoot, actualRoot)
|
|
// these are enumerated, so that the output is the actual difference
|
|
for _, diff := range different {
|
|
diff.FailedExpectation()
|
|
}
|
|
}
|
|
|
|
type Diff interface {
|
|
Path() string
|
|
FailedExpectation()
|
|
}
|
|
|
|
type contentdiff struct {
|
|
path, actual, expected string
|
|
}
|
|
|
|
func (d contentdiff) Path() string {
|
|
return d.path
|
|
}
|
|
|
|
// Run an expectation that will fail, giving an appropriate error
|
|
func (d contentdiff) FailedExpectation() {
|
|
Expect(d.actual).To(Equal(d.expected))
|
|
}
|
|
|
|
type dirfile struct {
|
|
abspath, path string
|
|
expectedRegularFile bool
|
|
}
|
|
|
|
func (d dirfile) Path() string {
|
|
return d.path
|
|
}
|
|
|
|
func (d dirfile) FailedExpectation() {
|
|
if d.expectedRegularFile {
|
|
Expect(d.path).To(BeARegularFile())
|
|
} else {
|
|
Expect(d.path).To(BeADirectory())
|
|
}
|
|
}
|
|
|
|
// DiffDirectories walks the two given directories, recursively, and
|
|
// reports relative paths for any files that are:
|
|
//
|
|
// (in actual but not expected, in expected but not actual, in both but different)
|
|
//
|
|
// It ignores dot directories (e.g., `.git/`) and Emacs backups (e.g.,
|
|
// `foo.yaml~`). It panics if it encounters any error apart from a
|
|
// file not found.
|
|
func DiffDirectories(actual, expected string) (actualonly []string, expectedonly []string, different []Diff) {
|
|
filepath.Walk(expected, func(expectedPath string, expectedInfo os.FileInfo, err error) error {
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
// ignore emacs backups
|
|
if strings.HasSuffix(expectedPath, "~") {
|
|
return nil
|
|
}
|
|
relPath := expectedPath[len(expected):]
|
|
actualPath := filepath.Join(actual, relPath)
|
|
// ignore dotfiles
|
|
if strings.HasPrefix(filepath.Base(expectedPath), ".") {
|
|
if expectedInfo.IsDir() {
|
|
return filepath.SkipDir
|
|
}
|
|
return nil
|
|
}
|
|
|
|
actualInfo, err := os.Stat(actualPath)
|
|
switch {
|
|
case err == nil:
|
|
break
|
|
case os.IsNotExist(err):
|
|
expectedonly = append(expectedonly, relPath)
|
|
return nil
|
|
default:
|
|
panic(err)
|
|
}
|
|
|
|
// file exists in both places
|
|
|
|
switch {
|
|
case actualInfo.IsDir() && expectedInfo.IsDir():
|
|
return nil // i.e., keep recursing
|
|
case actualInfo.IsDir() || expectedInfo.IsDir():
|
|
different = append(different, dirfile{path: relPath, abspath: actualPath, expectedRegularFile: actualInfo.IsDir()})
|
|
return nil
|
|
}
|
|
|
|
// both regular files
|
|
|
|
actualBytes, err := ioutil.ReadFile(actualPath)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
expectedBytes, err := ioutil.ReadFile(expectedPath)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
if string(actualBytes) != string(expectedBytes) {
|
|
different = append(different, contentdiff{path: relPath, actual: string(actualBytes), expected: string(expectedBytes)})
|
|
}
|
|
return nil
|
|
})
|
|
|
|
// every file and directory in the actual result should be expected
|
|
filepath.Walk(actual, func(actualPath string, actualInfo os.FileInfo, err error) error {
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
relPath := actualPath[len(actual):]
|
|
// ignore emacs backups
|
|
if strings.HasSuffix(actualPath, "~") {
|
|
return nil
|
|
}
|
|
// skip dotdirs
|
|
if actualInfo.IsDir() && strings.HasPrefix(filepath.Base(actualPath), ".") {
|
|
return filepath.SkipDir
|
|
}
|
|
// since I've already compared any file that exists in
|
|
// expected or both, I'm only concerned with files that appear
|
|
// in actual but not in expected.
|
|
expectedPath := filepath.Join(expected, relPath)
|
|
_, err = os.Stat(expectedPath)
|
|
switch {
|
|
case err == nil:
|
|
break
|
|
case os.IsNotExist(err):
|
|
actualonly = append(actualonly, relPath)
|
|
default:
|
|
panic(err)
|
|
}
|
|
return nil
|
|
})
|
|
return
|
|
}
|