@@ -33,15 +33,17 @@ func TestEveryComponentHasAnArtifactKind(t *testing.T) {
3333 }
3434}
3535
36- // TestTheFileVocabularyIsExactlyTheDeliveredFiles pins the split itself, as a
37- // literal, on both sides of the contract.
36+ // TestTheFileVocabularyIsExactlyTheDeliveredFiles pins which components have a
37+ // published file — the file-only ones plus FileImage — as a literal on both
38+ // sides of the contract.
3839func TestTheFileVocabularyIsExactlyTheDeliveredFiles (t * testing.T ) {
3940 want := []ComponentType {
4041 ComponentTypeInstaller ,
4142 ComponentTypeEngine ,
4243 ComponentTypeJaegerClickhouse ,
4344 ComponentTypeEngineRegistry ,
4445 ComponentTypeEngineScenario ,
46+ ComponentTypePentagi ,
4547 }
4648 got := map [ComponentType ]bool {}
4749 for _ , ct := range FileComponentTypes {
@@ -56,22 +58,34 @@ func TestTheFileVocabularyIsExactlyTheDeliveredFiles(t *testing.T) {
5658 for ct := range got {
5759 t .Errorf ("%s is delivered as a file but is not in the pinned list" , ct )
5860 }
59- if n := len (FileComponentTypes ) + len (ImageComponentTypes ); n != len (AllComponentTypes ) {
60- t .Errorf ("the two kinds cover %d components, the vocabulary has %d" , n , len (AllComponentTypes ))
61+ // FileImage sits in both lists, so the two lengths sum to more than the
62+ // vocabulary. Every component must still appear in at least one.
63+ seen := map [ComponentType ]struct {}{}
64+ for _ , ct := range FileComponentTypes {
65+ seen [ct ] = struct {}{}
66+ }
67+ for _ , ct := range ImageComponentTypes {
68+ seen [ct ] = struct {}{}
69+ }
70+ if len (seen ) != len (AllComponentTypes ) {
71+ t .Errorf ("the two kinds cover %d components, the vocabulary has %d" ,
72+ len (seen ), len (AllComponentTypes ))
6173 }
6274}
6375
6476// TestOnlyAFileHasAPackage exercises the `filecomp` tag over the WHOLE
6577// vocabulary — the shape that catches an omission rather than one that confirms
6678// the members already present.
6779//
68- // The list this replaced named two of the five, so an SDK asking for
69- // jaeger-clickhouse, engine-registry or engine-scenario refused locally before
70- // the request was ever sent.
80+ // The list this replaced named two of the five file-only components, so an SDK
81+ // asking for jaeger-clickhouse, engine-registry or engine-scenario refused
82+ // locally before the request was ever sent. Asking only the image/file delivery
83+ // question then cost one more: pentagi is FileImage, and treating that as "not
84+ // a file" refused the executable a running product replaces itself with.
7185//
72- // BOTH package requests are swept. Gating one and not the other is a real
73- // state this test exists to forbid: the SDK would send a metadata request the
74- // service refuses, while refusing the download of that same artefact itself.
86+ // BOTH package requests are swept. Gating one and not the other is a real state
87+ // this test exists to forbid: the SDK would send a metadata request the service
88+ // refuses, while refusing the download of that same artefact itself.
7589func TestOnlyAFileHasAPackage (t * testing.T ) {
7690 for _ , ct := range AllComponentTypes {
7791 requests := map [string ]IValid {
@@ -90,20 +104,71 @@ func TestOnlyAFileHasAPackage(t *testing.T) {
90104 }
91105 for name , request := range requests {
92106 err := request .Valid ()
93- switch ct .ArtifactKind () {
94- case ArtifactKindFile :
95- if err != nil {
96- t .Errorf ("%s is delivered as a file but %s rejects it: %v" , ct , name , err )
97- }
98- case ArtifactKindImage :
99- if err == nil {
100- t .Errorf ("%s is an image and has no package, but %s accepted it" , ct , name )
101- }
107+ if ct .IsFileComponent () && err != nil {
108+ t .Errorf ("%s has a published file but %s rejects it: %v" , ct , name , err )
109+ }
110+ if ! ct .IsFileComponent () && err == nil {
111+ t .Errorf ("%s has no package, but %s accepted it" , ct , name )
102112 }
103113 }
104114 }
105115}
106116
117+ // TestPentagiIsFileImage pins the one component that is both an image an
118+ // installer pulls and a file a running product downloads.
119+ //
120+ // It must stay in BOTH update-check lists: under `images` the service resolves
121+ // it against its registry reference, under `files` against the published
122+ // executable. Moving it to ArtifactKindFile takes it out of every installer's
123+ // image list; leaving it as ArtifactKindImage refuses the file half. FileImage
124+ // is both answers in the table, not a kind plus a side set.
125+ func TestPentagiIsFileImage (t * testing.T ) {
126+ if got := ComponentTypePentagi .ArtifactKind (); got != ArtifactKindFileImage {
127+ t .Errorf ("pentagi must be file-image, got %s" , got )
128+ }
129+ if ! ComponentTypePentagi .IsImageComponent () {
130+ t .Error ("pentagi must stay an image: an update check resolves it as one" )
131+ }
132+ if ! ComponentTypePentagi .IsFileComponent () {
133+ t .Error ("pentagi ships an executable a running product can replace itself with" )
134+ }
135+
136+ base := CheckUpdatesRequest {
137+ InstallerVersion : "1.0.0" ,
138+ InstallerOS : OSTypeLinux ,
139+ InstallerArch : ArchTypeAMD64 ,
140+ Strategy : UpdateStrategyPreview ,
141+ }
142+ asFile := base
143+ asFile .Files = []FileComponentInfo {{
144+ Component : ComponentTypePentagi ,
145+ Status : ComponentStatusRunning ,
146+ OS : OSTypeLinux ,
147+ Arch : ArchTypeAMD64 ,
148+ }}
149+ if err := asFile .Valid (); err != nil {
150+ t .Errorf ("pentagi reported under `files` must validate: %v" , err )
151+ }
152+ asImage := base
153+ asImage .Images = []ImageComponentInfo {{
154+ Component : ComponentTypePentagi ,
155+ Status : ComponentStatusRunning ,
156+ OS : OSTypeLinux ,
157+ Arch : ArchTypeAMD64 ,
158+ Repository : "vxcontrol/pentagi" ,
159+ Tag : "latest" ,
160+ }}
161+ if err := asImage .Valid (); err != nil {
162+ t .Errorf ("pentagi reported under `images` must validate: %v" , err )
163+ }
164+ both := base
165+ both .Images = asImage .Images
166+ both .Files = asFile .Files
167+ if err := both .Valid (); err != nil {
168+ t .Errorf ("pentagi reported under both lists must validate: %v" , err )
169+ }
170+ }
171+
107172// TestAComponentReportedUnderTheWrongKindIsRejected closes the hole that
108173// splitting the request lists left open.
109174//
@@ -126,17 +191,17 @@ func TestAComponentReportedUnderTheWrongKindIsRejected(t *testing.T) {
126191 t .Run ("an image reported under files" , func (t * testing.T ) {
127192 request := base ()
128193 request .Files = []FileComponentInfo {{
129- Component : ComponentTypePentagi ,
194+ Component : ComponentTypeScraper ,
130195 Status : ComponentStatusRunning ,
131196 OS : OSTypeLinux ,
132197 Arch : ArchTypeAMD64 ,
133198 Version : & version ,
134199 }}
135200 err := request .Valid ()
136201 if err == nil {
137- t .Fatal ("pentagi is an image; reporting it as a file must not validate" )
202+ t .Fatal ("scraper is an image; reporting it as a file must not validate" )
138203 }
139- if ! strings .Contains (err .Error (), "pentagi " ) {
204+ if ! strings .Contains (err .Error (), "scraper " ) {
140205 t .Errorf ("the error does not name the component: %v" , err )
141206 }
142207 })
0 commit comments