fix: support legacy factorPackIds format and tests

closes #1185
This commit is contained in:
blacktop
2026-05-03 11:33:19 -06:00
parent 7bd37ad024
commit c9a847a389
2 changed files with 133 additions and 4 deletions
+28 -4
View File
@@ -329,6 +329,31 @@ type BinaryImage struct {
Slide uint64 `json:"slide,omitempty"`
}
// FactorPackIDs accepts both the current string-list rollout encoding and the legacy object encoding.
type FactorPackIDs []string
func (ids *FactorPackIDs) UnmarshalJSON(data []byte) error {
if bytes.Equal(data, []byte("null")) {
*ids = nil
return nil
}
var values []string
arrayErr := json.Unmarshal(data, &values)
if arrayErr == nil {
*ids = values
return nil
}
var legacyObject struct{}
if err := json.Unmarshal(data, &legacyObject); err == nil {
*ids = nil
return nil
}
return arrayErr
}
func (bi *BinaryImage) UnmarshalJSON(b []byte) error {
var raw []json.RawMessage
if err := json.Unmarshal(b, &raw); err != nil {
@@ -696,10 +721,9 @@ type IPSPayload struct {
} `json:"legacyInfo"`
TrialInfo struct {
Rollouts []struct {
RolloutID string `json:"rolloutId,omitempty"`
FactorPackIds struct {
} `json:"factorPackIds"`
DeploymentID int `json:"deploymentId,omitempty"`
RolloutID string `json:"rolloutId,omitempty"`
FactorPackIds FactorPackIDs `json:"factorPackIds"`
DeploymentID int `json:"deploymentId,omitempty"`
} `json:"rollouts,omitempty"`
Experiments []struct {
TreatmentID string `json:"treatmentId,omitempty"`
+105
View File
@@ -0,0 +1,105 @@
package crashlog
import (
"encoding/json"
"os"
"path/filepath"
"slices"
"testing"
)
func TestIPSPayloadTrialInfoFactorPackIdsArray(t *testing.T) {
var payload IPSPayload
data := []byte(`{
"trialInfo": {
"rollouts": [
{
"rolloutId": "66d35d7fe4d6bf7664f40ddf",
"factorPackIds": ["68c1a34bd359577bbe8f2182"],
"deploymentId": 240000067
}
]
}
}`)
if err := json.Unmarshal(data, &payload); err != nil {
t.Fatalf("json.Unmarshal: %v", err)
}
rollouts := payload.TrialInfo.Rollouts
if len(rollouts) != 1 {
t.Fatalf("expected 1 rollout, got %d", len(rollouts))
}
assertFactorPackIDs(t, rollouts[0].FactorPackIds, "68c1a34bd359577bbe8f2182")
}
func TestOpenIPSAcceptsTrialInfoFactorPackIdsArray(t *testing.T) {
path := filepath.Join(t.TempDir(), "ios26.ips")
data := []byte(`{"bug_type":"309","os_version":"iPhone OS 26.0 (23A000)"}
{
"modelCode": "iPhone17,1",
"trialInfo": {
"rollouts": [
{
"rolloutId": "66d35d7fe4d6bf7664f40ddf",
"factorPackIds": ["68c1a34bd359577bbe8f2182"],
"deploymentId": 240000067
}
]
}
}`)
if err := os.WriteFile(path, data, 0o600); err != nil {
t.Fatalf("os.WriteFile: %v", err)
}
ips, err := OpenIPS(path, &Config{})
if err != nil {
t.Fatalf("OpenIPS: %v", err)
}
rollouts := ips.Payload.TrialInfo.Rollouts
if len(rollouts) != 1 {
t.Fatalf("expected 1 rollout, got %d", len(rollouts))
}
assertFactorPackIDs(t, rollouts[0].FactorPackIds, "68c1a34bd359577bbe8f2182")
}
func TestIPSPayloadTrialInfoFactorPackIdsLegacyObject(t *testing.T) {
var payload IPSPayload
data := []byte(`{
"trialInfo": {
"rollouts": [
{
"rolloutId": "66d35d7fe4d6bf7664f40ddf",
"factorPackIds": {},
"deploymentId": 240000067
}
]
}
}`)
if err := json.Unmarshal(data, &payload); err != nil {
t.Fatalf("json.Unmarshal: %v", err)
}
rollouts := payload.TrialInfo.Rollouts
if len(rollouts) != 1 {
t.Fatalf("expected 1 rollout, got %d", len(rollouts))
}
assertFactorPackIDs(t, rollouts[0].FactorPackIds)
}
func TestFactorPackIdsRejectsInvalidShape(t *testing.T) {
var factorPackIDs FactorPackIDs
if err := json.Unmarshal([]byte(`"68c1a34bd359577bbe8f2182"`), &factorPackIDs); err == nil {
t.Fatal("expected invalid scalar factorPackIds to fail")
}
}
func assertFactorPackIDs(t *testing.T, got FactorPackIDs, want ...string) {
t.Helper()
if !slices.Equal(got, want) {
t.Fatalf("unexpected factor pack IDs: got %#v, want %#v", got, want)
}
}