blob: 21c9250015d14df96aa7013d6f00b618e0a8c9b8 [file]
// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package ids
import (
"fmt"
"testing"
"go.chromium.org/turboci/proto/go/internal/test/assert"
)
func ExampleFromString() {
// A simple workplan ID
wp, err := FromString("Lmy-workplan")
if err != nil {
panic(err)
}
fmt.Println(wp.GetWorkPlan().GetId())
// A check on that workplan
chk, err := FromString("Lmy-workplan:Cmy-check")
if err != nil {
panic(err)
}
fmt.Println(chk.GetCheck().GetId())
// A stage on that workplan
st, err := FromString("Lmy-workplan:Smy-stage")
if err != nil {
panic(err)
}
fmt.Println(st.GetStage().GetId())
// An invalid string
_, err = FromString("Lmy-workplan:Xwhatever")
fmt.Println(err)
// Output:
// my-workplan
// my-check
// my-stage
// token 1 in "Lmy-workplan:Xwhatever": unexpected key 'X'
}
func TestFromStringErrorConditions(t *testing.T) {
t.Parallel()
tests := []struct {
name string
input string
expectedErr string
}{
{
name: "Empty input string",
input: "",
expectedErr: "",
},
{
name: "Empty token in middle",
input: "Lwp::Cchk",
expectedErr: `token 1 in "Lwp::Cchk" was empty?`,
},
{
name: "Empty token at end",
input: "Lwp:Cchk:",
expectedErr: `token 2 in "Lwp:Cchk:" was empty?`,
},
{
name: "Invalid idx - non-integer",
input: "Lwp:Cchk:Rabc",
expectedErr: `token 2 in "Lwp:Cchk:Rabc": bad idx: strconv.ParseInt: parsing "abc": invalid syntax`,
},
{
name: "Invalid idx - negative",
input: "Lwp:Cchk:R-1",
expectedErr: `token 2 in "Lwp:Cchk:R-1": bad idx: must be > 0`,
},
{
name: "Invalid timestamp - malformed",
input: "Lwp:Cchk:Vbadts",
expectedErr: `token 2 in "Lwp:Cchk:Vbadts": bad timestamp: needed seconds/nanos`,
},
{
name: "Invalid timestamp - non-integer seconds",
input: "Lwp:Cchk:Vabc/123",
expectedErr: `token 2 in "Lwp:Cchk:Vabc/123": bad timestamp: parsing seconds "abc"`,
},
{
name: "Invalid timestamp - non-integer nanos",
input: "Lwp:Cchk:V123/abc",
expectedErr: `token 2 in "Lwp:Cchk:V123/abc": bad timestamp: parsing nanos "abc"`,
},
{
name: "Missing required previous ID part - R without C",
input: "Lwp:R1",
expectedErr: `token 1 in "Lwp:R1": expected "Check", got "WorkPlan"`,
},
{
name: "Unexpected key for current ID type - L after L",
input: "Lwp1:Lwp2",
expectedErr: `token 1 in "Lwp1:Lwp2": unexpected key 'L'`,
},
{
name: "Unexpected key for current ID type - C after C",
input: "Lwp:Cchk1:Cchk2",
expectedErr: `token 2 in "Lwp:Cchk1:Cchk2": expected "WorkPlan", got "Check"`,
},
{
name: "WorkPlan with only key, no trimmed part - L",
input: "L",
expectedErr: "",
},
{
name: "Token with only key, no trimmed part - C",
input: "Lwp:C",
expectedErr: `token 1 in "Lwp:C": unexpected empty token`,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
t.Parallel()
_, err := FromString(test.input)
if test.expectedErr == "" {
assert.NoErr(t, err)
} else {
assert.ErrLike(t, err, test.expectedErr)
}
})
}
}