Skip to content

Commit 7af8a18

Browse files
DeviceInfracopybara-github
authored andcommitted
Internal change
PiperOrigin-RevId: 894511804
1 parent b6495b4 commit 7af8a18

9 files changed

Lines changed: 290 additions & 9 deletions

File tree

src/java/com/google/devtools/mobileharness/fe/v6/service/host/provider/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ java_library(
2525
srcs = glob(["*.java"]),
2626
deps = [
2727
"//src/devtools/mobileharness/fe/v6/service/proto/host:host_resources_java_proto",
28+
"//src/java/com/google/devtools/mobileharness/fe/v6/service/util",
2829
"//src/java/com/google/devtools/mobileharness/shared/util/auto:auto_value",
2930
"@maven//:com_google_guava_guava",
3031
"@maven//:javax_inject_jsr330_api",

src/java/com/google/devtools/mobileharness/fe/v6/service/host/provider/HostAuxiliaryInfoProvider.java

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,78 @@
1818

1919
import com.google.common.util.concurrent.ListenableFuture;
2020
import com.google.devtools.mobileharness.fe.v6.service.proto.host.DiagnosticLink;
21+
import com.google.devtools.mobileharness.fe.v6.service.util.UniverseScope;
2122
import java.util.List;
2223
import java.util.Optional;
2324

2425
/** Provides auxiliary information about hosts, such as release info and pass-through flags. */
2526
public interface HostAuxiliaryInfoProvider {
2627

2728
/** Fetches release information and host attributes from internal services. */
28-
ListenableFuture<Optional<HostReleaseInfo>> getHostReleaseInfo(String hostName);
29+
ListenableFuture<Optional<HostReleaseInfo>> getHostReleaseInfo(
30+
String hostName, UniverseScope universe);
31+
32+
/**
33+
* @deprecated Use {@link #getHostReleaseInfo(String, UniverseScope)} instead. TODO: Remove after
34+
* all callers are migrated to UniverseScope.
35+
*/
36+
@Deprecated
37+
default ListenableFuture<Optional<HostReleaseInfo>> getHostReleaseInfo(
38+
String hostName, String universe) {
39+
return getHostReleaseInfo(hostName, UniverseScope.fromString(universe));
40+
}
41+
42+
/**
43+
* @deprecated Use {@link #getHostReleaseInfo(String, UniverseScope)} instead. TODO: Remove after
44+
* all callers are migrated to UniverseScope.
45+
*/
46+
@Deprecated
47+
default ListenableFuture<Optional<HostReleaseInfo>> getHostReleaseInfo(String hostName) {
48+
return getHostReleaseInfo(hostName, new UniverseScope.SelfUniverse());
49+
}
2950

3051
/** Fetches the legacy pass-through flags for the lab server. */
31-
ListenableFuture<Optional<String>> getPassThroughFlags(String hostName);
52+
ListenableFuture<Optional<String>> getPassThroughFlags(String hostName, UniverseScope universe);
53+
54+
/**
55+
* @deprecated Use {@link #getPassThroughFlags(String, UniverseScope)} instead. TODO: Remove after
56+
* all callers are migrated to UniverseScope.
57+
*/
58+
@Deprecated
59+
default ListenableFuture<Optional<String>> getPassThroughFlags(String hostName, String universe) {
60+
return getPassThroughFlags(hostName, UniverseScope.fromString(universe));
61+
}
62+
63+
/**
64+
* @deprecated Use {@link #getPassThroughFlags(String, UniverseScope)} instead. TODO: Remove after
65+
* all callers are migrated to UniverseScope.
66+
*/
67+
@Deprecated
68+
default ListenableFuture<Optional<String>> getPassThroughFlags(String hostName) {
69+
return getPassThroughFlags(hostName, new UniverseScope.SelfUniverse());
70+
}
3271

3372
/** Fetches the diagnostic links for the host. */
3473
ListenableFuture<List<DiagnosticLink>> getDiagnosticLinks(
35-
String hostName, Optional<String> labType);
74+
String hostName, Optional<String> labType, UniverseScope universe);
75+
76+
/**
77+
* @deprecated Use {@link #getDiagnosticLinks(String, Optional, UniverseScope)} instead. TODO:
78+
* Remove after all callers are migrated to UniverseScope.
79+
*/
80+
@Deprecated
81+
default ListenableFuture<List<DiagnosticLink>> getDiagnosticLinks(
82+
String hostName, Optional<String> labType, String universe) {
83+
return getDiagnosticLinks(hostName, labType, UniverseScope.fromString(universe));
84+
}
85+
86+
/**
87+
* @deprecated Use {@link #getDiagnosticLinks(String, Optional, UniverseScope)} instead. TODO:
88+
* Remove after all callers are migrated to UniverseScope.
89+
*/
90+
@Deprecated
91+
default ListenableFuture<List<DiagnosticLink>> getDiagnosticLinks(
92+
String hostName, Optional<String> labType) {
93+
return getDiagnosticLinks(hostName, labType, new UniverseScope.SelfUniverse());
94+
}
3695
}

src/java/com/google/devtools/mobileharness/fe/v6/service/host/provider/OssHostAuxiliaryInfoProviderImpl.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.google.common.collect.ImmutableList;
2222
import com.google.common.util.concurrent.ListenableFuture;
2323
import com.google.devtools.mobileharness.fe.v6.service.proto.host.DiagnosticLink;
24+
import com.google.devtools.mobileharness.fe.v6.service.util.UniverseScope;
2425
import java.util.List;
2526
import java.util.Optional;
2627
import javax.inject.Inject;
@@ -32,18 +33,20 @@ public class OssHostAuxiliaryInfoProviderImpl implements HostAuxiliaryInfoProvid
3233
OssHostAuxiliaryInfoProviderImpl() {}
3334

3435
@Override
35-
public ListenableFuture<Optional<HostReleaseInfo>> getHostReleaseInfo(String hostName) {
36+
public ListenableFuture<Optional<HostReleaseInfo>> getHostReleaseInfo(
37+
String hostName, UniverseScope universe) {
3638
return immediateFuture(Optional.empty());
3739
}
3840

3941
@Override
40-
public ListenableFuture<Optional<String>> getPassThroughFlags(String hostName) {
42+
public ListenableFuture<Optional<String>> getPassThroughFlags(
43+
String hostName, UniverseScope universe) {
4144
return immediateFuture(Optional.empty());
4245
}
4346

4447
@Override
4548
public ListenableFuture<List<DiagnosticLink>> getDiagnosticLinks(
46-
String hostName, Optional<String> labType) {
49+
String hostName, Optional<String> labType, UniverseScope universe) {
4750
return immediateFuture(ImmutableList.of());
4851
}
4952
}

src/java/com/google/devtools/mobileharness/fe/v6/service/util/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package(
1919
default_applicable_licenses = ["//:license"],
2020
default_visibility = [
2121
"//java/com/google/devtools/mobileharness/fe/v6/service:__subpackages__",
22+
"//javatests/com/google/devtools/mobileharness/fe/v6/service:__subpackages__",
2223
"//src/java/com/google/devtools/mobileharness/fe/v6/service:__subpackages__",
2324
"//src/javatests/com/google/devtools/mobileharness/fe/v6/service:__subpackages__",
2425
],
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright 2022 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.devtools.mobileharness.fe.v6.service.util;
18+
19+
import javax.inject.Inject;
20+
import javax.inject.Singleton;
21+
22+
/**
23+
* Factory for creating {@link UniverseScope} instances based on environment and request parameters.
24+
*/
25+
@Singleton
26+
public class UniverseFactory {
27+
28+
private final Environment environment;
29+
30+
@Inject
31+
UniverseFactory(Environment environment) {
32+
this.environment = environment;
33+
}
34+
35+
/**
36+
* Creates a {@link UniverseScope} instance from a universe string.
37+
*
38+
* @param universeStr the universe string from the request
39+
* @return the {@link UniverseScope} instance
40+
* @throws IllegalArgumentException if the universe string is invalid for the current environment
41+
*/
42+
public UniverseScope create(String universeStr) {
43+
if (environment.isGoogleInternal()) {
44+
if (universeStr.isEmpty() || universeStr.equals("google_1p")) {
45+
return UniverseScope.SELF;
46+
} else {
47+
return new UniverseScope.RoutedUniverse(universeStr);
48+
}
49+
} else {
50+
if (universeStr.isEmpty()) {
51+
return UniverseScope.SELF;
52+
} else {
53+
throw new IllegalArgumentException(
54+
"Non-empty universe is not supported in OSS/ATS environment.");
55+
}
56+
}
57+
}
58+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright 2022 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.devtools.mobileharness.fe.v6.service.util;
18+
19+
/**
20+
* Represents the universe scope for routing and feature enablement.
21+
*
22+
* <p>This sealed interface replaces the {@code Universe} proto for internal service logic,
23+
* providing compile-time type safety with exactly two states:
24+
*
25+
* <ul>
26+
* <li>{@link SelfUniverse} — the local (google_1p) universe
27+
* <li>{@link RoutedUniverse} — a remote ATS controller universe
28+
* </ul>
29+
*/
30+
public sealed interface UniverseScope {
31+
32+
/** A singleton {@link SelfUniverse} instance for convenience. */
33+
UniverseScope SELF = new SelfUniverse();
34+
35+
/** Represents the local (google_1p) universe. */
36+
record SelfUniverse() implements UniverseScope {}
37+
38+
/** Represents a remote ATS controller universe, identified by its controller ID. */
39+
record RoutedUniverse(String atsControllerId) implements UniverseScope {}
40+
41+
/**
42+
* Creates a {@link UniverseScope} from a legacy universe string.
43+
*
44+
* <p>This is intended for use in {@code @Deprecated} bridge methods to convert legacy
45+
* String-based callers to the new type-safe API during the migration period.
46+
*
47+
* @deprecated Use {@link UniverseFactory#create(String)} instead, which includes environment
48+
* validation. TODO: Remove after all callers are migrated to UniverseScope.
49+
*/
50+
@Deprecated
51+
static UniverseScope fromString(String universe) {
52+
return (universe.isEmpty() || universe.equals("google_1p"))
53+
? SELF
54+
: new RoutedUniverse(universe);
55+
}
56+
}

src/javatests/com/google/devtools/mobileharness/fe/v6/service/host/provider/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ java_library(
2626
srcs = glob(["*.java"]),
2727
deps = [
2828
"//src/java/com/google/devtools/mobileharness/fe/v6/service/host/provider",
29+
"//src/java/com/google/devtools/mobileharness/fe/v6/service/util",
2930
"//src/javatests/com/google/devtools/mobileharness/builddefs:truth",
3031
"@maven//:junit_junit",
3132
],

src/javatests/com/google/devtools/mobileharness/fe/v6/service/host/provider/OssHostAuxiliaryInfoProviderImplTest.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import static com.google.common.truth.Truth.assertThat;
2020

21+
import com.google.devtools.mobileharness.fe.v6.service.util.UniverseScope;
2122
import java.util.Optional;
2223
import org.junit.Before;
2324
import org.junit.Test;
@@ -36,17 +37,28 @@ public void setUp() {
3637

3738
@Test
3839
public void getHostReleaseInfo_returnsEmpty() throws Exception {
39-
assertThat(ossHostAuxiliaryInfoProviderImpl.getHostReleaseInfo("host").get()).isEmpty();
40+
assertThat(
41+
ossHostAuxiliaryInfoProviderImpl
42+
.getHostReleaseInfo("host", new UniverseScope.SelfUniverse())
43+
.get())
44+
.isEmpty();
4045
}
4146

4247
@Test
4348
public void getPassThroughFlags_returnsEmpty() throws Exception {
44-
assertThat(ossHostAuxiliaryInfoProviderImpl.getPassThroughFlags("host").get()).isEmpty();
49+
assertThat(
50+
ossHostAuxiliaryInfoProviderImpl
51+
.getPassThroughFlags("host", new UniverseScope.SelfUniverse())
52+
.get())
53+
.isEmpty();
4554
}
4655

4756
@Test
4857
public void getDiagnosticLinks_returnsEmpty() throws Exception {
49-
assertThat(ossHostAuxiliaryInfoProviderImpl.getDiagnosticLinks("host", Optional.empty()).get())
58+
assertThat(
59+
ossHostAuxiliaryInfoProviderImpl
60+
.getDiagnosticLinks("host", Optional.empty(), new UniverseScope.SelfUniverse())
61+
.get())
5062
.isEmpty();
5163
}
5264
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright 2022 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.devtools.mobileharness.fe.v6.service.util;
18+
19+
import static com.google.common.truth.Truth.assertThat;
20+
import static org.junit.Assert.assertThrows;
21+
import static org.mockito.Mockito.when;
22+
23+
import org.junit.Before;
24+
import org.junit.Rule;
25+
import org.junit.Test;
26+
import org.junit.runner.RunWith;
27+
import org.junit.runners.JUnit4;
28+
import org.mockito.Mock;
29+
import org.mockito.junit.MockitoJUnit;
30+
import org.mockito.junit.MockitoRule;
31+
32+
@RunWith(JUnit4.class)
33+
public final class UniverseFactoryTest {
34+
35+
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
36+
37+
@Mock private Environment mockEnvironment;
38+
39+
private UniverseFactory universeFactory;
40+
41+
@Before
42+
public void setUp() {
43+
universeFactory = new UniverseFactory(mockEnvironment);
44+
}
45+
46+
@Test
47+
public void create_internal_emptyUniverse_returnsSelfUniverse() {
48+
when(mockEnvironment.isGoogleInternal()).thenReturn(true);
49+
50+
UniverseScope universe = universeFactory.create("");
51+
52+
assertThat(universe).isInstanceOf(UniverseScope.SelfUniverse.class);
53+
}
54+
55+
@Test
56+
public void create_internal_google1pUniverse_returnsSelfUniverse() {
57+
when(mockEnvironment.isGoogleInternal()).thenReturn(true);
58+
59+
UniverseScope universe = universeFactory.create("google_1p");
60+
61+
assertThat(universe).isInstanceOf(UniverseScope.SelfUniverse.class);
62+
}
63+
64+
@Test
65+
public void create_internal_otherUniverse_returnsRoutedUniverse() {
66+
when(mockEnvironment.isGoogleInternal()).thenReturn(true);
67+
68+
UniverseScope universe = universeFactory.create("my_universe");
69+
70+
assertThat(universe).isInstanceOf(UniverseScope.RoutedUniverse.class);
71+
assertThat(((UniverseScope.RoutedUniverse) universe).atsControllerId())
72+
.isEqualTo("my_universe");
73+
}
74+
75+
@Test
76+
public void create_oss_emptyUniverse_returnsSelfUniverse() {
77+
when(mockEnvironment.isGoogleInternal()).thenReturn(false);
78+
79+
UniverseScope universe = universeFactory.create("");
80+
81+
assertThat(universe).isInstanceOf(UniverseScope.SelfUniverse.class);
82+
}
83+
84+
@Test
85+
public void create_oss_nonEmptyUniverse_throwsException() {
86+
when(mockEnvironment.isGoogleInternal()).thenReturn(false);
87+
88+
assertThrows(IllegalArgumentException.class, () -> universeFactory.create("my_universe"));
89+
}
90+
}

0 commit comments

Comments
 (0)