Skip to content

[duplicate-code] Duplicate Code Pattern: DIFC Label CheckFlow Implementations #1721

@github-actions

Description

@github-actions

🔍 Duplicate Code Pattern: DIFC Label CheckFlow Implementations

Part of duplicate code analysis: #1719

Summary

SecrecyLabel.CheckFlow and IntegrityLabel.CheckFlow in internal/difc/labels.go share ~32 lines of near-identical structure: nil guard, double RLock, tag-set iteration, and diagnostic logging. The only meaningful difference is the direction of the subset check (secrecy checks source ⊆ target; integrity checks target ⊆ source). This is the largest duplication in the file.

Duplication Details

Pattern: Nil-Guard + Double RLock + Tag Subset Check

  • Severity: High

  • Occurrences: 2 instances

  • Locations:

    • internal/difc/labels.go (lines ~189–220) — SecrecyLabel.CheckFlow
    • internal/difc/labels.go (lines ~273–304) — IntegrityLabel.CheckFlow
  • Code Sample:

// SecrecyLabel.CheckFlow — checks source ⊆ target
func (l *SecrecyLabel) CheckFlow(target *SecrecyLabel) (bool, []Tag) {
    if l == nil || l.Label == nil {
        return true, nil
    }
    if target == nil || target.Label == nil {
        if l.Label.IsEmpty() { return true, nil }
        extraTags := l.Label.GetTags()
        logLabels.Printf("Secrecy CheckFlow denied: ...")
        return false, extraTags
    }
    l.Label.mu.RLock(); defer l.Label.mu.RUnlock()
    target.Label.mu.RLock(); defer target.Label.mu.RUnlock()
    var extraTags []Tag
    for tag := range l.Label.tags {
        if _, ok := target.Label.tags[tag]; !ok {
            extraTags = append(extraTags, tag)
        }
    }
    ...
    return len(extraTags) == 0, extraTags
}

// IntegrityLabel.CheckFlow — checks target ⊆ source (reversed)
func (l *IntegrityLabel) CheckFlow(target *IntegrityLabel) (bool, []Tag) {
    if l == nil || l.Label == nil {
        if target == nil || target.Label == nil || target.Label.IsEmpty() { return true, nil }
        missingTags := target.Label.GetTags()
        logLabels.Printf("Integrity CheckFlow denied: ...")
        return false, missingTags
    }
    if target == nil || target.Label == nil { return true, nil }
    l.Label.mu.RLock(); defer l.Label.mu.RUnlock()
    target.Label.mu.RLock(); defer target.Label.mu.RUnlock()
    var missingTags []Tag
    for tag := range target.Label.tags {  // iterates target, not source
        if _, ok := l.Label.tags[tag]; !ok {
            missingTags = append(missingTags, tag)
        }
    }
    ...
    return len(missingTags) == 0, missingTags
}

Impact Analysis

  • Maintainability: Fixing a locking bug or adding tracing requires changes in two places
  • Bug Risk: The nil-guard ordering already differs slightly between the two — future edits risk further divergence
  • Code Bloat: ~32 lines could be shared via a generic subset-check helper

Refactoring Recommendations

  1. Extract a private checkLabelSubset helper

    // checkLabelSubset checks whether all tags in `haystack` exist in `needleSet`.
    // Returns false + the missing/extra tags if the check fails.
    func checkLabelSubset(haystack, needleSet *Label, logPrefix string) (bool, []Tag) {
        haystack.mu.RLock(); defer haystack.mu.RUnlock()
        needleSet.mu.RLock(); defer needleSet.mu.RUnlock()
        var missing []Tag
        for tag := range haystack.tags {
            if _, ok := needleSet.tags[tag]; !ok {
                missing = append(missing, tag)
            }
        }
        if len(missing) > 0 {
            logLabels.Printf("%s: tags not in target set: %v", logPrefix, missing)
        }
        return len(missing) == 0, missing
    }

    Then both CheckFlow methods handle only their specific nil-guard logic and delegate the set comparison.

    • Estimated effort: 1 hour (careful with nil guards and test coverage)
    • Benefits: Single locking strategy, consistent tag-comparison semantics
  2. Alternatively, use Go generics (Go 1.18+) to create a single typed checkFlow[T labelType] function if the type system permits.

Implementation Checklist

  • Review both CheckFlow implementations side-by-side
  • Write/verify unit tests covering nil cases and subset checks
  • Extract checkLabelSubset private helper
  • Update both CheckFlow methods to delegate
  • Run make test-unit to confirm no regressions

Parent Issue

See parent analysis report: #1719
Related to #1719

Generated by Duplicate Code Detector ·

  • expires on Mar 17, 2026, 2:56 AM UTC

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions