func checkExif(f *models.File) (passed bool, err error) { var cmdOut []byte args := []string{"-j", f.FullPath} if cmdOut, err = exec.Command("exiftool", args...).Output(); err != nil { return false, errors.Errorf("There was an error retrieving file %s metadata: %s", f.FullPath, err) } var exifs []models.Exif if err = json.Unmarshal(cmdOut, &exifs); err != nil { return false, errors.Errorf("There was an error parsing file %s metadata: %s", f.FullPath, err) } f.Exif = exifs[0] f.Save() workflowExif, _ := reflections.Items(f.Workflow.Exif) var checkError string = "" for fieldName, fieldValue := range workflowExif { if isZeroOfUnderlyingType(fieldValue) { continue } if value, err := reflections.GetField(f.Exif, fieldName); err != nil { return false, errors.Errorf("There was an error validating Exif for file %s. Field '%s' doesn't exist:\n %s", f.FullPath, fieldName, err) } else { if value != fieldValue { checkError += fmt.Sprintf("Field '%s' has value '%v', but '%v' was expected\n", fieldName, value, fieldValue) } } } if checkError != "" { return false, errors.Errorf("There was an error validating Exif for file %s.\n%s", f.FullPath, checkError) } else { return true, nil } }
func detectWorkflows(file *models.File, workflows models.Workflows) { contentType, _ := file.Attributes["content_type"].(string) line, _ := file.Attributes["line"].(string) if err := workflows.DetectWorkflows(contentType, line); err != nil { file.Status = models.HAS_NO_WORKFLOW file.Error = fmt.Sprintf("Could not detect workflows for file: %#v. %s\n", file, err) l.Println(file.Error) } if len(workflows) > 0 { if len(workflows) == 1 { file.Status = models.HAS_WORKFLOW file.Workflow = workflows[0] } else { file.Status = models.HAS_MANY_WORKFLOWS file.Error = fmt.Sprintf("Matched more than one workflow\n: %#v", workflows) l.Println(file.Error) } } else { file.Status = models.HAS_NO_WORKFLOW file.Error = fmt.Sprintf("No workflows matched by content_type %q and line %q", contentType, line) l.Println(file.Error) } }
func TestFileManagerSpec(t *testing.T) { Convey("FileManager", t, func() { Convey("Importing files", func() { Convey("Having one file manager", func() { initFileManager() Reset(func() { fileManager.Destroy() fileManager = nil }) Convey("It should prevent watching a->b and a->c simultaneously", func() { fileManager.Watch(watchDir1, "a->b") err = fileManager.Watch(watchDir1, "a->c") So(err, ShouldNotBeNil) }) Convey("It should create source and target directories if not exist", func() { fileManager.Watch(watchDir1, "label") _, err = os.Stat(watchDir1) So(err, ShouldBeNil) _, err = os.Stat(targetDir1) So(err, ShouldBeNil) }) Convey("It should copy existing file from watch dir to target dir", func() { os.MkdirAll(watchDir1, os.ModePerm) createTestFile(watchFile1) fileManager.Watch(watchDir1, "label") So(func() interface{} { files, _ := filepath.Glob(targetFile1v1) return files }, utils.Eventually, 3*time.Second, assertions.ShouldNotBeNil) }) Convey("It should copy only files, not directories", func() { subdir := filepath.Join(watchDir1, "subdir") os.MkdirAll(subdir, os.ModePerm) fileManager.Watch(watchDir1, targetDir1) time.Sleep(1 * time.Second) _, err = os.Stat(subdir) So(err, ShouldBeNil) }) Convey("It should copy new file from watch dir to target dir", func() { fileManager.Watch(watchDir1, targetDir1) createTestFile(watchFile1) So(func() interface{} { files, _ := filepath.Glob(targetFile1v1) return files }, utils.Eventually, 3*time.Second, assertions.ShouldNotBeNil) }) Convey("It should copy 2 new different files to target dir", func() { fileManager.Watch(watchDir1, targetDir1) watchFile2 := filepath.Join(watchDir1, "file2.txt") targetFile2 := filepath.Join(targetDir1, "*/*/v01/file2.txt") createTestFile(watchFile1) createTestFile(watchFile2) So(func() interface{} { files, _ := filepath.Glob(targetFile1v1) return files }, utils.Eventually, 3*time.Second, assertions.ShouldNotBeNil) So(func() interface{} { files, _ := filepath.Glob(targetFile2) return files }, utils.Eventually, 3*time.Second, assertions.ShouldNotBeNil) }) }) Convey("Having two file managers", func() { initFileManager() if fileManager2, err = fm.NewFM(targetDir2); err != nil { panic(fmt.Sprintf("Unable to initialize FileManager2: %v", err)) } Reset(func() { fileManager.Destroy() fileManager2.Destroy() fileManager = nil fileManager2 = nil }) Convey("both file managers should move files to target directories", func() { fileManager.Watch(watchDir1, targetDir1) fileManager2.Watch(watchDir2, targetDir2) createTestFile(watchFile1) createTestFile(watchFile2) So(func() interface{} { files, _ := filepath.Glob(targetFile1v1) return files }, utils.Eventually, 3*time.Second, assertions.ShouldNotBeNil) So(func() interface{} { files, _ := filepath.Glob(targetFile2v1) return files }, utils.Eventually, 3*time.Second, assertions.ShouldNotBeNil) }) Convey("after destroying and recreating both file managers files should be moved to target directories", func() { fileManager.Destroy() fileManager2.Destroy() fileManager = nil fileManager2 = nil if fileManager, err = fm.NewFM(targetDir1, fm.WatchPair{watchDir1, "fm1"}); err != nil { panic(fmt.Sprintf("Unable to initialize FileManager: %v", err)) } if fileManager2, err = fm.NewFM(targetDir2, fm.WatchPair{watchDir2, "fm2"}); err != nil { panic(fmt.Sprintf("Unable to initialize FileManager2: %v", err)) } createTestFile(watchFile1) createTestFile(watchFile2) So(func() interface{} { files, _ := filepath.Glob(targetFile1v1) return files }, utils.Eventually, 3*time.Second, assertions.ShouldNotBeNil) So(func() interface{} { files, _ := filepath.Glob(targetFile2v1) return files }, utils.Eventually, 3*time.Second, assertions.ShouldNotBeNil) }) }) Convey("copying more than once the same file to the same dir", func() { initFileManager() Reset(func() { fileManager.Destroy() fileManager = nil }) Convey("both files must be versioned", func() { fileManager.Watch(watchDir1, "label") createTestFile(watchFile1) So(func() interface{} { files, _ := filepath.Glob(targetFile1v1) return files }, utils.Eventually, 3*time.Second, assertions.ShouldNotBeNil) createTestFile(watchFile1) So(func() interface{} { files, _ := filepath.Glob(targetFile1v1) return files }, utils.Eventually, 3*time.Second, assertions.ShouldNotBeNil) }) }) }) Convey("Support handlers", func() { initFileManager() Reset(func() { fileManager.Destroy() fileManager = nil }) Convey("It registers handlers and calls them", func() { handlerWasCalled := false handler := func(file *models.File) (err error) { handlerWasCalled = true return } fileManager.Register(handler) fileManager.Watch(watchDir1, targetDir1) createTestFile(watchFile1) So(func() interface{} { return handlerWasCalled }, utils.Eventually, 3*time.Second, assertions.ShouldBeTrue) }) Convey("It calls handler with proper params", func() { handlerWasCalled := "" handler := func(file *models.File) (err error) { handlerWasCalled = file.SourcePath + " " + file.TargetDir l.Println(handlerWasCalled) return } fileManager.Register(handler) fileManager.Watch(watchDir1, targetDir1) createTestFile(watchFile1) So(func() interface{} { return strings.HasPrefix(handlerWasCalled, watchFile1+" "+targetDir1) }, utils.Eventually, 3*time.Second, assertions.ShouldBeTrue) }) Convey("calls more than one handler", func() { handlersCalled := 0 handler1 := func(file *models.File) (err error) { handlersCalled++ return } handler2 := func(file *models.File) (err error) { handlersCalled++ return } fileManager.Register(handler1, handler2) fileManager.Watch(watchDir1, targetDir1) createTestFile(watchFile1) So(func() interface{} { return handlersCalled == 2 }, utils.Eventually, 3*time.Second, assertions.ShouldBeTrue) }) Convey("calls handlers until error", func() { handlersCalled := false handler1 := func(file *models.File) (err error) { return errors.New("new error") } handler2 := func(file *models.File) (err error) { handlersCalled = true return } fileManager.Register(handler1, handler2) fileManager.Watch(watchDir1, targetDir1) createTestFile(watchFile1) So(func() interface{} { return handlersCalled }, utils.Eventually, 3*time.Second, assertions.ShouldBeFalse) }) }) Convey("Database Integrity", func() { initFileManager() Reset(func() { fileManager.Destroy() fileManager = nil }) Convey("It should create versions for the same file and version must increment by one", func() { fileManager.Watch(watchDir1, "label") createTestFile(watchFile1) file := models.File{FileName: filepath.Base(watchFile1)} So(func() interface{} { return file.Load() }, utils.Eventually, 3*time.Second, assertions.ShouldBeNil) So(file.Version, ShouldEqual, int64(1)) files, _ := filepath.Glob(targetFile1v1) So(files, ShouldNotBeNil) createTestFile(watchFile1) file = models.File{FileName: filepath.Base(watchFile1), Version: 2} So(func() interface{} { return file.Load() }, utils.Eventually, 3*time.Second, assertions.ShouldBeNil) files, _ = filepath.Glob(targetFile1v2) So(files, ShouldNotBeNil) }) Convey("It should create a file record in db", func() { fileManager.Watch(watchDir1, "label") createTestFile(watchFile1) //check that file is in db file := models.File{FileName: filepath.Base(watchFile1)} So(func() interface{} { return file.Load() }, utils.Eventually, 3*time.Second, assertions.ShouldBeNil) }) }) SkipConvey("Validating files", func() { Convey("It should validate id3", func() { }) Convey("When file is valid", func() { Convey("mark file as valid", func() { }) }) Convey("When file is invalid", func() { Convey("mark file as invalid", func() { }) Convey("send notification to admin", func() { }) }) }) }) }