package version_test import ( "regexp" "strings" "testing" "workshop.perforce.com/p4lf/internal/version" ) func TestGet_ReturnsNonEmptySemVer(t *testing.T) { info := version.Get() if info.SemVer == "" { t.Error("SemVer should not be empty") } } func TestString_ContainsSemVer(t *testing.T) { s := version.String() if !strings.Contains(s, "p4lf") { t.Errorf("version string should contain 'p4lf': %q", s) } if !strings.Contains(s, version.SemVer) { t.Errorf("version string should contain SemVer %q: %q", version.SemVer, s) } } // TestStreamParsing validates the depot-path → stream extraction logic used // inside Get(), by replicating the same regex against representative inputs. func TestStreamParsing(t *testing.T) { idRe := regexp.MustCompile(`\$Id:\s*(//[^\s#]+)(#\d+)\s*\$`) cases := []struct { input string wantStream string wantRevision string }{ { input: "$Id: //p4lf/dev/internal/version/version.go#3 $", wantStream: "//p4lf/dev", wantRevision: "#3", }, { input: "$Id: //p4lf/main/internal/version/version.go#12 $", wantStream: "//p4lf/main", wantRevision: "#12", }, { input: "$Id: //p4lf/r26.1/internal/version/version.go#1 $", wantStream: "//p4lf/r26.1", wantRevision: "#1", }, } for _, tc := range cases { m := idRe.FindStringSubmatch(tc.input) if m == nil { t.Errorf("regex did not match %q", tc.input) continue } depotPath, revision := m[1], m[2] if revision != tc.wantRevision { t.Errorf("input %q: revision got %q, want %q", tc.input, revision, tc.wantRevision) } parts := strings.SplitN(strings.TrimPrefix(depotPath, "//"), "/", 3) stream := "" if len(parts) >= 2 { stream = "//" + parts[0] + "/" + parts[1] } if stream != tc.wantStream { t.Errorf("input %q: stream got %q, want %q", tc.input, stream, tc.wantStream) } } } func TestChangeParsing(t *testing.T) { changeRe := regexp.MustCompile(`\$Change:\s*(\d+)\s*\$`) cases := []struct{ input, want string }{ {"$Change: 32819 $", "32819"}, {"$Change: 1 $", "1"}, {"$Change: 999999 $", "999999"}, } for _, tc := range cases { m := changeRe.FindStringSubmatch(tc.input) if m == nil { t.Errorf("no match for %q", tc.input) continue } if m[1] != tc.want { t.Errorf("input %q: got %q, want %q", tc.input, m[1], tc.want) } } } func TestDateTimeParsing(t *testing.T) { dateRe := regexp.MustCompile(`\$DateTime:\s*(\d{4}/\d{2}/\d{2})`) cases := []struct{ input, want string }{ {"$DateTime: 2026/06/25 15:00:00 $", "2026/06/25"}, {"$DateTime: 2099/12/31 23:59:59 $", "2099/12/31"}, } for _, tc := range cases { m := dateRe.FindStringSubmatch(tc.input) if m == nil { t.Errorf("no match for %q", tc.input) continue } if m[1] != tc.want { t.Errorf("input %q: got %q, want %q", tc.input, m[1], tc.want) } } }