diff --git a/plumbing/reference_validation.go b/plumbing/reference_validation.go new file mode 100644 index 000000000..bf3192a3a --- /dev/null +++ b/plumbing/reference_validation.go @@ -0,0 +1,311 @@ +package plumbing + +import ( + "errors" + "regexp" + "strings" +) + +type ActionChoice int + +const ( + // This skips the check + SKIP ActionChoice = iota + // This removes the issue when possible + SANITIZE + // This throws an error and must be fixed + VALIDATE +) + +var ( + ErrRefLeadingDot = errors.New("ref name cannot begin with a dot") + ErrRefTrailingLock = errors.New("ref name cannot end with .lock") + ErrRefAtLeastOneForwardSlash = errors.New("ref name must have at least one forward slash") + ErrRefDoubleDots = errors.New("ref name cannot include two consecutive dots") + ErrRefExcludedCharacters = errors.New("ref name cannot include many special characters") + ErrRefLeadingForwardSlash = errors.New("ref name cannot start with a forward slash") + ErrRefTrailingForwardSlash = errors.New("ref name cannot end with a forward slash") + ErrRefConsecutiveForwardSlashes = errors.New("ref name cannot have consectutive forward slashes") + ErrRefTrailingDot = errors.New("ref name cannot end with a dot") + ErrRefAtOpenBrace = errors.New("ref name cannot include at-open-brace") + ErrRefOnlyAtSign = errors.New("ref name cannot only be an at sign") +) + +var ( + PatternLeadingDot = regexp.MustCompile(`^\.`) + PatternTrailingLock = regexp.MustCompile(`\.lock$`) + PatternAtLeastOneForwardSlash = regexp.MustCompile(`^[^/]+$`) + PatternDoubleDots = regexp.MustCompile(`\.\.`) + PatternExcludedCharacters = regexp.MustCompile(`[\000-\037\177 ~^:?*[]+`) + PatternLeadingForwardSlash = regexp.MustCompile(`^/`) + PatternTrailingForwardSlash = regexp.MustCompile(`/$`) + PatternConsecutiveForwardSlashes = regexp.MustCompile(`//+`) + PatternTrailingDot = regexp.MustCompile(`\.$`) + PatternAtOpenBrace = regexp.MustCompile(`@{`) + PatternExcludedCharactersAlternate = regexp.MustCompile(`[\000-\037\177 ~^:?[]+`) + PatternOneAllowedAsterisk = regexp.MustCompile(`^[^*]+?\*?[^*]+?$`) + PatternOnlyAtSign = regexp.MustCompile(`^@$`) +) + +type CheckRefOptions struct { + // They must contain at least one / + // If the --allow-onelevel option is used, this rule is waived. + AllowOneLevel bool + // If this option is enabled, is allowed to contain a + // single * in the refspec + RefSpecPattern bool + // Normalize refname by removing any leading slash (/) characters and + // collapsing runs of adjacent slashes between name components into + // a single slash. + Normalize bool +} + +type ActionOptions struct { + + // no slash-separated component can begin with a dot . + HandleLeadingDot ActionChoice + + // no slash-separated component can end with the sequence .lock + HandleTrailingLock ActionChoice + // They must contain at least one /. + HandleAtLeastOneForwardSlash ActionChoice + // They cannot have two consecutive dots .. anywhere. + HandleDoubleDots ActionChoice + // They cannot have ASCII control characters (i.e. bytes whose values + // are lower than \040, or \177 DEL), space, tilde ~, caret ^, or + // colon : anywhere. + // They cannot have question-mark ?, asterisk *, or open + // bracket [ anywhere + // They cannot contain a \ + HandleExcludedCharacters ActionChoice + // They cannot begin or end with a slash / + HandleLeadingForwardSlash ActionChoice + // They cannot begin or end with a slash / or contain + // multiple consecutive slashes + HandleTrailingForwardSlash ActionChoice + // They cannot contain multiple consecutive slashes + HandleConsecutiveForwardSlashes ActionChoice + // They cannot end with a dot . + HandleTrailingDot ActionChoice + // They cannot contain a sequence @{ + HandleAtOpenBrace ActionChoice + // They cannot be the single character @ + HandleOnlyAtSign ActionChoice +} + +// https://git-scm.com/docs/git-check-ref-format +// git-check-ref-format +type RefNameChecker struct { + Name ReferenceName + CheckRefOptions CheckRefOptions + ActionOptions ActionOptions +} + +func NewCheckRefOptions(default_value bool) *CheckRefOptions { + return &CheckRefOptions{ + AllowOneLevel: default_value, + RefSpecPattern: default_value, + Normalize: default_value, + } +} + +func NewActionOptions(default_value ActionChoice) *ActionOptions { + return &ActionOptions{ + HandleLeadingDot: default_value, + HandleTrailingLock: default_value, + HandleAtLeastOneForwardSlash: default_value, + HandleDoubleDots: default_value, + HandleExcludedCharacters: default_value, + HandleLeadingForwardSlash: default_value, + HandleTrailingForwardSlash: default_value, + HandleConsecutiveForwardSlashes: default_value, + HandleTrailingDot: default_value, + HandleAtOpenBrace: default_value, + HandleOnlyAtSign: default_value, + } +} + +func NewRefNameChecker( + name ReferenceName, + ref_options CheckRefOptions, + action_options ActionOptions, +) *RefNameChecker { + return &RefNameChecker{ + Name: name, + CheckRefOptions: ref_options, + ActionOptions: action_options, + } +} + +func (v *RefNameChecker) HandleLeadingDot() error { + switch v.ActionOptions.HandleLeadingDot { + case VALIDATE: + if PatternLeadingDot.MatchString(v.Name.String()) { + return ErrRefLeadingDot + } + break + case SANITIZE: + v.Name = ReferenceName(PatternLeadingDot.ReplaceAllString(v.Name.String(), "")) + } + return nil +} + +func (v *RefNameChecker) HandleTrailingLock() error { + switch v.ActionOptions.HandleTrailingLock { + case VALIDATE: + if PatternTrailingLock.MatchString(v.Name.String()) { + return ErrRefTrailingLock + } + break + case SANITIZE: + v.Name = ReferenceName(PatternTrailingLock.ReplaceAllString(v.Name.String(), "")) + } + return nil +} + +func (v *RefNameChecker) HandleAtLeastOneForwardSlash() error { + if SKIP == v.ActionOptions.HandleAtLeastOneForwardSlash { + return nil + } + count := strings.Count(v.Name.String(), "/") + if 1 > count { + if v.CheckRefOptions.AllowOneLevel { + return nil + } + return ErrRefAtLeastOneForwardSlash + } + return nil +} + +func (v *RefNameChecker) HandleDoubleDots() error { + switch v.ActionOptions.HandleDoubleDots { + case VALIDATE: + if PatternDoubleDots.MatchString(v.Name.String()) { + return ErrRefDoubleDots + } + break + case SANITIZE: + v.Name = ReferenceName(PatternDoubleDots.ReplaceAllString(v.Name.String(), "")) + } + return nil +} + +func (v *RefNameChecker) HandleExcludedCharacters() error { + switch v.ActionOptions.HandleExcludedCharacters { + case VALIDATE: + if PatternExcludedCharacters.MatchString(v.Name.String()) { + return ErrRefExcludedCharacters + } + break + case SANITIZE: + if v.CheckRefOptions.RefSpecPattern && PatternOneAllowedAsterisk.MatchString(v.Name.String()) { + v.Name = ReferenceName(PatternExcludedCharactersAlternate.ReplaceAllString(v.Name.String(), "")) + + } else { + v.Name = ReferenceName(PatternExcludedCharacters.ReplaceAllString(v.Name.String(), "")) + } + } + return nil +} + +func (v *RefNameChecker) HandleLeadingForwardSlash() error { + switch v.ActionOptions.HandleLeadingForwardSlash { + case VALIDATE: + if PatternLeadingForwardSlash.MatchString(v.Name.String()) { + return ErrRefLeadingForwardSlash + } + break + case SANITIZE: + v.Name = ReferenceName(PatternLeadingForwardSlash.ReplaceAllString(v.Name.String(), "")) + } + return nil +} + +func (v *RefNameChecker) HandleTrailingForwardSlash() error { + switch v.ActionOptions.HandleTrailingForwardSlash { + case VALIDATE: + if PatternTrailingForwardSlash.MatchString(v.Name.String()) { + return ErrRefTrailingForwardSlash + } + break + case SANITIZE: + v.Name = ReferenceName(PatternTrailingForwardSlash.ReplaceAllString(v.Name.String(), "")) + } + return nil +} + +func (v *RefNameChecker) HandleConsecutiveForwardSlashes() error { + if SKIP == v.ActionOptions.HandleConsecutiveForwardSlashes { + return nil + } + if PatternConsecutiveForwardSlashes.MatchString(v.Name.String()) { + if SANITIZE == v.ActionOptions.HandleConsecutiveForwardSlashes { + if v.CheckRefOptions.Normalize { + v.Name = ReferenceName(PatternConsecutiveForwardSlashes.ReplaceAllString(v.Name.String(), "/")) + return nil + } + } + return ErrRefConsecutiveForwardSlashes + } + return nil +} + +func (v *RefNameChecker) HandleTrailingDot() error { + switch v.ActionOptions.HandleTrailingDot { + case VALIDATE: + if PatternTrailingDot.MatchString(v.Name.String()) { + return ErrRefTrailingDot + } + break + case SANITIZE: + v.Name = ReferenceName(PatternTrailingDot.ReplaceAllString(v.Name.String(), "")) + } + return nil +} + +func (v *RefNameChecker) HandleAtOpenBrace() error { + switch v.ActionOptions.HandleAtOpenBrace { + case VALIDATE: + if PatternAtOpenBrace.MatchString(v.Name.String()) { + return ErrRefAtOpenBrace + } + break + case SANITIZE: + v.Name = ReferenceName(PatternAtOpenBrace.ReplaceAllString(v.Name.String(), "")) + } + return nil +} + +func (v *RefNameChecker) HandleOnlyAtSign() error { + if SKIP == v.ActionOptions.HandleOnlyAtSign { + return nil + } + if PatternOnlyAtSign.MatchString(v.Name.String()) { + return ErrRefOnlyAtSign + } + return nil +} + +// This runs everything +func (v *RefNameChecker) CheckRefName() error { + handles := []func() error{ + v.HandleLeadingDot, + v.HandleTrailingLock, + v.HandleAtLeastOneForwardSlash, + v.HandleDoubleDots, + v.HandleExcludedCharacters, + v.HandleLeadingForwardSlash, + v.HandleTrailingForwardSlash, + v.HandleConsecutiveForwardSlashes, + v.HandleTrailingDot, + v.HandleAtOpenBrace, + v.HandleOnlyAtSign, + } + for _, handle := range handles { + err := handle() + if nil != err { + return err + } + } + return nil +} diff --git a/plumbing/reference_validation_testing.go b/plumbing/reference_validation_testing.go new file mode 100644 index 000000000..81859b81a --- /dev/null +++ b/plumbing/reference_validation_testing.go @@ -0,0 +1,388 @@ +package plumbing + +import ( + "fmt" + . "gopkg.in/check.v1" +) + +type ReferenceValidationSuite struct { + Checker RefNameChecker +} + +var _ = Suite(&ReferenceValidationSuite{}) + +var ( + LeadingDotNames = []string{ + ".a/name", + "a/name", + } + TrailingLockNames = []string{ + "a/name.lock", + "a/name", + } + AtLeastOneForwardSlashNames = []string{ + "aname", + "a/name", + } + DoubleDotsNames = []string{ + "a..name", + "aname", + } + ExcludedCharactersNames = []string{ + `an^ame`, + "aname", + `a/lon*ger/name`, + `a/lon*ger/na*me`, + `a/longer/name`, + } + LeadingForwardSlashNames = []string{ + "/a/name", + "a/name", + } + TrailingForwardSlashNames = []string{ + "a/name/", + "a/name", + } + ConsecutiveForwardSlashesNames = []string{ + "a//name", + "a/name", + "a///longer///name", + "a/longer/name", + } + TrailingDotNames = []string{ + "a/name.", + "a/name", + } + AtOpenBraceNames = []string{ + `a/na@{me`, + `a/name`, + } + OnlyAtSignNames = []string{ + `@`, + } +) + +func (s *ReferenceValidationSuite) TestValidateHandleLeadingDot(c *C) { + s.Checker.ActionOptions.HandleLeadingDot = VALIDATE + s.Checker.Name = ReferenceName(LeadingDotNames[0]) + err := s.Checker.HandleLeadingDot() + c.Assert(err, ErrorMatches, fmt.Sprint(ErrRefLeadingDot)) + s.Checker.Name = ReferenceName(LeadingDotNames[1]) + err = s.Checker.HandleLeadingDot() + c.Assert(err, IsNil) +} + +func (s *ReferenceValidationSuite) TestSanitizeHandleLeadingDot(c *C) { + s.Checker.ActionOptions.HandleLeadingDot = SANITIZE + s.Checker.Name = ReferenceName(LeadingDotNames[0]) + err := s.Checker.HandleLeadingDot() + c.Assert(err, IsNil) + c.Assert(s.Checker.Name.String(), Equals, LeadingDotNames[1]) +} + +func (s *ReferenceValidationSuite) TestSkipHandleLeadingDot(c *C) { + s.Checker.ActionOptions.HandleLeadingDot = SKIP + for _, name := range LeadingDotNames { + s.Checker.Name = ReferenceName(name) + err := s.Checker.HandleLeadingDot() + c.Assert(err, IsNil) + } +} + +func (s *ReferenceValidationSuite) TestValidateHandleTrailingLock(c *C) { + s.Checker.ActionOptions.HandleTrailingLock = VALIDATE + s.Checker.Name = ReferenceName(TrailingLockNames[0]) + err := s.Checker.HandleTrailingLock() + c.Assert(err, ErrorMatches, fmt.Sprint(ErrRefTrailingLock)) + s.Checker.Name = ReferenceName(TrailingLockNames[1]) + err = s.Checker.HandleTrailingLock() + c.Assert(err, IsNil) +} + +func (s *ReferenceValidationSuite) TestSkipHandleTrailingLock(c *C) { + s.Checker.ActionOptions.HandleTrailingLock = SKIP + for _, name := range TrailingLockNames { + s.Checker.Name = ReferenceName(name) + err := s.Checker.HandleTrailingLock() + c.Assert(err, IsNil) + } +} + +func (s *ReferenceValidationSuite) TestSanitizeHandleTrailingLock(c *C) { + s.Checker.ActionOptions.HandleTrailingLock = SANITIZE + s.Checker.Name = ReferenceName(TrailingLockNames[0]) + err := s.Checker.HandleTrailingLock() + c.Assert(err, IsNil) + c.Assert(s.Checker.Name.String(), Equals, TrailingLockNames[1]) +} + +func (s *ReferenceValidationSuite) TestValidateAtLeastOneForwardSlash(c *C) { + for _, setting := range []ActionChoice{VALIDATE, SANITIZE} { + s.Checker.CheckRefOptions.AllowOneLevel = false + s.Checker.ActionOptions.HandleAtLeastOneForwardSlash = setting + s.Checker.Name = ReferenceName(AtLeastOneForwardSlashNames[0]) + err := s.Checker.HandleAtLeastOneForwardSlash() + c.Assert(err, ErrorMatches, fmt.Sprint(ErrRefAtLeastOneForwardSlash)) + s.Checker.Name = ReferenceName(AtLeastOneForwardSlashNames[1]) + err = s.Checker.HandleAtLeastOneForwardSlash() + c.Assert(err, IsNil) + s.Checker.Name = ReferenceName(AtLeastOneForwardSlashNames[0]) + s.Checker.CheckRefOptions.AllowOneLevel = true + err = s.Checker.HandleAtLeastOneForwardSlash() + c.Assert(err, IsNil) + } +} + +func (s *ReferenceValidationSuite) TestSkipHandleAtLeastOneForwardSlash(c *C) { + s.Checker.ActionOptions.HandleAtLeastOneForwardSlash = SKIP + for _, name := range AtLeastOneForwardSlashNames { + s.Checker.Name = ReferenceName(name) + err := s.Checker.HandleAtLeastOneForwardSlash() + c.Assert(err, IsNil) + } +} + +func (s *ReferenceValidationSuite) TestValidateHandleDoubleDots(c *C) { + s.Checker.ActionOptions.HandleDoubleDots = VALIDATE + s.Checker.Name = ReferenceName(DoubleDotsNames[0]) + err := s.Checker.HandleDoubleDots() + c.Assert(err, ErrorMatches, fmt.Sprint(ErrRefDoubleDots)) + s.Checker.Name = ReferenceName(DoubleDotsNames[1]) + err = s.Checker.HandleDoubleDots() + c.Assert(err, IsNil) +} + +func (s *ReferenceValidationSuite) TestSanitizeHandleDoubleDots(c *C) { + s.Checker.ActionOptions.HandleDoubleDots = SANITIZE + s.Checker.Name = ReferenceName(DoubleDotsNames[0]) + err := s.Checker.HandleDoubleDots() + c.Assert(err, IsNil) + c.Assert(s.Checker.Name.String(), Equals, DoubleDotsNames[1]) +} + +func (s *ReferenceValidationSuite) TestSkipHandleDoubleDots(c *C) { + s.Checker.ActionOptions.HandleDoubleDots = SKIP + for _, name := range DoubleDotsNames { + s.Checker.Name = ReferenceName(name) + err := s.Checker.HandleDoubleDots() + c.Assert(err, IsNil) + } +} + +func (s *ReferenceValidationSuite) TestValidateHandleExcludedCharacters(c *C) { + s.Checker.ActionOptions.HandleExcludedCharacters = VALIDATE + s.Checker.Name = ReferenceName(ExcludedCharactersNames[0]) + err := s.Checker.HandleExcludedCharacters() + c.Assert(err, ErrorMatches, fmt.Sprint(ErrRefExcludedCharacters)) + s.Checker.Name = ReferenceName(ExcludedCharactersNames[1]) + err = s.Checker.HandleExcludedCharacters() + c.Assert(err, IsNil) +} + +func (s *ReferenceValidationSuite) TestSanitizeHandleExcludedCharacters(c *C) { + s.Checker.ActionOptions.HandleExcludedCharacters = SANITIZE + s.Checker.Name = ReferenceName(ExcludedCharactersNames[0]) + err := s.Checker.HandleExcludedCharacters() + c.Assert(err, IsNil) + c.Assert(s.Checker.Name.String(), Equals, ExcludedCharactersNames[1]) + s.Checker.Name = ReferenceName(ExcludedCharactersNames[2]) + err = s.Checker.HandleExcludedCharacters() + c.Assert(err, IsNil) + c.Assert(s.Checker.Name.String(), Equals, ExcludedCharactersNames[4]) + s.Checker.Name = ReferenceName(ExcludedCharactersNames[3]) + err = s.Checker.HandleExcludedCharacters() + c.Assert(err, IsNil) + c.Assert(s.Checker.Name.String(), Equals, ExcludedCharactersNames[4]) + s.Checker.CheckRefOptions.RefSpecPattern = true + s.Checker.Name = ReferenceName(ExcludedCharactersNames[2]) + err = s.Checker.HandleExcludedCharacters() + c.Assert(err, IsNil) + c.Assert(s.Checker.Name.String(), Equals, ExcludedCharactersNames[2]) + s.Checker.Name = ReferenceName(ExcludedCharactersNames[3]) + err = s.Checker.HandleExcludedCharacters() + c.Assert(err, IsNil) + c.Assert(s.Checker.Name.String(), Equals, ExcludedCharactersNames[4]) +} + +func (s *ReferenceValidationSuite) TestSkipHandleExcludedCharacters(c *C) { + s.Checker.ActionOptions.HandleExcludedCharacters = SKIP + for _, name := range ExcludedCharactersNames { + s.Checker.Name = ReferenceName(name) + err := s.Checker.HandleExcludedCharacters() + c.Assert(err, IsNil) + } +} + +func (s *ReferenceValidationSuite) TestValidateHandleLeadingForwardSlash(c *C) { + s.Checker.ActionOptions.HandleLeadingForwardSlash = VALIDATE + s.Checker.Name = ReferenceName(LeadingForwardSlashNames[0]) + err := s.Checker.HandleLeadingForwardSlash() + c.Assert(err, ErrorMatches, fmt.Sprint(ErrRefLeadingForwardSlash)) + s.Checker.Name = ReferenceName(LeadingForwardSlashNames[1]) + err = s.Checker.HandleLeadingForwardSlash() + c.Assert(err, IsNil) +} + +func (s *ReferenceValidationSuite) TestSanitizeHandleLeadingForwardSlash(c *C) { + s.Checker.ActionOptions.HandleLeadingForwardSlash = SANITIZE + s.Checker.Name = ReferenceName(LeadingForwardSlashNames[0]) + err := s.Checker.HandleLeadingForwardSlash() + c.Assert(err, IsNil) + c.Assert(s.Checker.Name.String(), Equals, LeadingForwardSlashNames[1]) +} + +func (s *ReferenceValidationSuite) TestSkipHandleLeadingForwardSlash(c *C) { + s.Checker.ActionOptions.HandleLeadingForwardSlash = SKIP + for _, name := range LeadingForwardSlashNames { + s.Checker.Name = ReferenceName(name) + err := s.Checker.HandleLeadingForwardSlash() + c.Assert(err, IsNil) + } +} + +func (s *ReferenceValidationSuite) TestValidateHandleTrailingForwardSlash(c *C) { + s.Checker.ActionOptions.HandleTrailingForwardSlash = VALIDATE + s.Checker.Name = ReferenceName(TrailingForwardSlashNames[0]) + err := s.Checker.HandleTrailingForwardSlash() + c.Assert(err, ErrorMatches, fmt.Sprint(ErrRefTrailingForwardSlash)) + s.Checker.Name = ReferenceName(TrailingForwardSlashNames[1]) + err = s.Checker.HandleTrailingForwardSlash() + c.Assert(err, IsNil) +} + +func (s *ReferenceValidationSuite) TestSanitizeHandleTrailingForwardSlash(c *C) { + s.Checker.ActionOptions.HandleTrailingForwardSlash = SANITIZE + s.Checker.Name = ReferenceName(TrailingForwardSlashNames[0]) + err := s.Checker.HandleTrailingForwardSlash() + c.Assert(err, IsNil) + c.Assert(s.Checker.Name.String(), Equals, TrailingForwardSlashNames[1]) +} + +func (s *ReferenceValidationSuite) TestSkipHandleTrailingForwardSlash(c *C) { + s.Checker.ActionOptions.HandleTrailingForwardSlash = SKIP + for _, name := range TrailingForwardSlashNames { + s.Checker.Name = ReferenceName(name) + err := s.Checker.HandleTrailingForwardSlash() + c.Assert(err, IsNil) + } +} + +func (s *ReferenceValidationSuite) TestValidateHandleConsecutiveForwardSlashes(c *C) { + s.Checker.ActionOptions.HandleConsecutiveForwardSlashes = VALIDATE + for index, name := range ConsecutiveForwardSlashesNames { + s.Checker.Name = ReferenceName(name) + err := s.Checker.HandleConsecutiveForwardSlashes() + if 1 == index%2 { + c.Assert(err, IsNil) + } else { + c.Assert(err, ErrorMatches, fmt.Sprint(ErrRefConsecutiveForwardSlashes)) + } + + } +} + +func (s *ReferenceValidationSuite) TestSanitizeHandleConsecutiveForwardSlashes(c *C) { + + for _, element := range []int{0, 2} { + s.Checker.CheckRefOptions.Normalize = true + s.Checker.ActionOptions.HandleConsecutiveForwardSlashes = SANITIZE + s.Checker.Name = ReferenceName(ConsecutiveForwardSlashesNames[element+0]) + err := s.Checker.HandleConsecutiveForwardSlashes() + c.Assert(err, IsNil) + c.Assert(s.Checker.Name.String(), Equals, ConsecutiveForwardSlashesNames[element+1]) + s.Checker.CheckRefOptions.Normalize = false + s.Checker.Name = ReferenceName(ConsecutiveForwardSlashesNames[element+0]) + err = s.Checker.HandleConsecutiveForwardSlashes() + c.Assert(err, ErrorMatches, fmt.Sprint(ErrRefConsecutiveForwardSlashes)) + } +} + +func (s *ReferenceValidationSuite) TestSkipHandleConsecutiveForwardSlashes(c *C) { + s.Checker.ActionOptions.HandleConsecutiveForwardSlashes = SKIP + for _, name := range ConsecutiveForwardSlashesNames { + s.Checker.Name = ReferenceName(name) + err := s.Checker.HandleConsecutiveForwardSlashes() + c.Assert(err, IsNil) + } +} + +func (s *ReferenceValidationSuite) TestValidateHandleTrailingDot(c *C) { + s.Checker.ActionOptions.HandleTrailingDot = VALIDATE + s.Checker.Name = ReferenceName(TrailingDotNames[0]) + err := s.Checker.HandleTrailingDot() + c.Assert(err, ErrorMatches, fmt.Sprint(ErrRefTrailingDot)) + s.Checker.Name = ReferenceName(TrailingDotNames[1]) + err = s.Checker.HandleTrailingDot() + c.Assert(err, IsNil) +} + +func (s *ReferenceValidationSuite) TestSanitizeHandleTrailingDot(c *C) { + s.Checker.ActionOptions.HandleTrailingDot = SANITIZE + s.Checker.Name = ReferenceName(TrailingDotNames[0]) + err := s.Checker.HandleTrailingDot() + c.Assert(err, IsNil) + c.Assert(s.Checker.Name.String(), Equals, TrailingDotNames[1]) +} + +func (s *ReferenceValidationSuite) TestSkipHandleTrailingDot(c *C) { + s.Checker.ActionOptions.HandleTrailingDot = SKIP + for _, name := range TrailingDotNames { + s.Checker.Name = ReferenceName(name) + err := s.Checker.HandleTrailingDot() + c.Assert(err, IsNil) + } +} + +func (s *ReferenceValidationSuite) TestValidateHandleAtOpenBrace(c *C) { + s.Checker.ActionOptions.HandleAtOpenBrace = VALIDATE + s.Checker.Name = ReferenceName(AtOpenBraceNames[0]) + err := s.Checker.HandleAtOpenBrace() + c.Assert(err, ErrorMatches, fmt.Sprint(ErrRefAtOpenBrace)) + s.Checker.Name = ReferenceName(AtOpenBraceNames[1]) + err = s.Checker.HandleAtOpenBrace() + c.Assert(err, IsNil) +} + +func (s *ReferenceValidationSuite) TestSanitizeHandleAtOpenBrace(c *C) { + s.Checker.ActionOptions.HandleAtOpenBrace = SANITIZE + s.Checker.Name = ReferenceName(AtOpenBraceNames[0]) + err := s.Checker.HandleAtOpenBrace() + c.Assert(err, IsNil) + c.Assert(s.Checker.Name.String(), Equals, AtOpenBraceNames[1]) +} + +func (s *ReferenceValidationSuite) TestSkipHandleAtOpenBrace(c *C) { + s.Checker.ActionOptions.HandleAtOpenBrace = SKIP + for _, name := range AtOpenBraceNames { + s.Checker.Name = ReferenceName(name) + err := s.Checker.HandleAtOpenBrace() + c.Assert(err, IsNil) + } +} + +func (s *ReferenceValidationSuite) TestValidateHandleOnlyAtSign(c *C) { + s.Checker.ActionOptions.HandleOnlyAtSign = SANITIZE + s.Checker.Name = ReferenceName(OnlyAtSignNames[0]) + err := s.Checker.HandleOnlyAtSign() + c.Assert(err, ErrorMatches, fmt.Sprint(ErrRefOnlyAtSign)) +} + +func (s *ReferenceValidationSuite) TestSanitizeHandleOnlyAtSign(c *C) { + s.Checker.ActionOptions.HandleOnlyAtSign = SANITIZE + s.Checker.Name = ReferenceName(OnlyAtSignNames[0]) + err := s.Checker.HandleOnlyAtSign() + c.Assert(err, ErrorMatches, fmt.Sprint(ErrRefOnlyAtSign)) +} + +func (s *ReferenceValidationSuite) TestSkipHandleOnlyAtSign(c *C) { + s.Checker.ActionOptions.HandleOnlyAtSign = SKIP + for _, name := range OnlyAtSignNames { + s.Checker.Name = ReferenceName(name) + err := s.Checker.HandleOnlyAtSign() + c.Assert(err, IsNil) + } +} + +// func (s *ReferenceValidationSuite) TestCheckRefName(c *C) { +// s.Checker.CheckRefName() +// }