Skip to content

Commit ce1ab8b

Browse files
authored
Merge pull request #1085 from IABTechLab/aaq-UID2-3393-remove-assertions
Removing assertions from code and replacing with relevant exceptions
2 parents 6303b64 + 24ab08e commit ce1ab8b

File tree

9 files changed

+141
-72
lines changed

9 files changed

+141
-72
lines changed

src/main/java/com/uid2/operator/monitoring/StatsCollectorHandler.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ public StatsCollectorHandler(IStatsCollectorQueue _statCollectorQueue, Vertx ver
2020

2121
@Override
2222
public void handle(RoutingContext routingContext) {
23-
assert routingContext != null;
23+
if (routingContext == null) {
24+
throw new NullPointerException();
25+
}
2426

2527
//setAuthClient() has not yet been called, so getAuthClient() would return null. This is resolved by using addBodyEndHandler()
2628
routingContext.addBodyEndHandler(v -> addStatsMessageToQueue(routingContext));

src/main/java/com/uid2/operator/monitoring/StatsCollectorVerticle.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,6 @@ public void handleMessage(Message message) {
8888
return;
8989
}
9090

91-
assert messageItem != null;
92-
9391
String path = messageItem.getPath();
9492
String apiVersion = "v0";
9593
String endpoint = path.substring(1);

src/main/java/com/uid2/operator/service/UIDOperatorService.java

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ public class UIDOperatorService implements IUIDOperatorService {
4747
private final Duration refreshIdentityAfter;
4848

4949
private final OperatorIdentity operatorIdentity;
50-
private final TokenVersion tokenVersionToUseIfNotV4;
51-
private final int advertisingTokenV4Percentage;
52-
private final Set<Integer> siteIdsUsingV4Tokens;
50+
protected final TokenVersion tokenVersionToUseIfNotV4;
51+
protected final int advertisingTokenV4Percentage;
52+
protected final Set<Integer> siteIdsUsingV4Tokens;
5353
private final TokenVersion refreshTokenVersion;
5454
private final boolean identityV3Enabled;
5555

@@ -319,12 +319,4 @@ private GlobalOptoutResult getGlobalOptOutResult(UserIdentity userIdentity, bool
319319
Instant result = this.optOutStore.getLatestEntry(userIdentity);
320320
return new GlobalOptoutResult(result);
321321
}
322-
323-
public TokenVersion getAdvertisingTokenVersionForTests(int siteId) {
324-
assert this.advertisingTokenV4Percentage == 0 || this.advertisingTokenV4Percentage == 100; //we want tests to be deterministic
325-
if (this.siteIdsUsingV4Tokens.contains(siteId)) {
326-
return TokenVersion.V4;
327-
}
328-
return this.advertisingTokenV4Percentage == 100 ? TokenVersion.V4 : this.tokenVersionToUseIfNotV4;
329-
}
330322
}

src/main/java/com/uid2/operator/service/V2RequestUtil.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,12 @@ public static void handleRefreshTokenInResponseBody(JsonObject bodyJson, KeyMana
172172
.appendInt(refreshKey.getId())
173173
.appendBytes(encrypted)
174174
.getBytes());
175-
assert modifiedToken.length() == V2_REFRESH_PAYLOAD_LENGTH;
175+
if (modifiedToken.length() != V2_REFRESH_PAYLOAD_LENGTH) {
176+
final String errorMsg = "Generated refresh token's length=" + modifiedToken.length()
177+
+ " is not equal to=" + V2_REFRESH_PAYLOAD_LENGTH;
178+
LOGGER.error(errorMsg);
179+
throw new IllegalArgumentException(errorMsg);
180+
}
176181

177182
bodyJson.put("refresh_token", modifiedToken);
178183
bodyJson.put("refresh_response_key", refreshResponseKey);

src/main/java/com/uid2/operator/store/CloudSyncOptOutStore.java

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,11 @@ private IndexUpdateMessage getIndexUpdateMessage(Instant now, Collection<String>
525525
ium.addDeltaFile(f);
526526
else if (OptOutUtils.isPartitionFile(f))
527527
ium.addPartitionFile(f);
528-
else assert false;
528+
else {
529+
final String errorMsg = "File to index " + f + " is not of type delta or partition";
530+
LOGGER.error(errorMsg);
531+
throw new IllegalStateException(errorMsg);
532+
}
529533
}
530534

531535
Collection<String> indexedNonSynthetic = indexedFiles.stream()
@@ -538,7 +542,12 @@ else if (OptOutUtils.isPartitionFile(f))
538542

539543
Instant tsOld = OptOutUtils.lastPartitionTimestamp(indexedNonSynthetic);
540544
Instant tsNew = OptOutUtils.lastPartitionTimestamp(newNonSynthetic);
541-
assert tsOld == Instant.EPOCH || tsNew == Instant.EPOCH || tsOld.isBefore(tsNew);
545+
if (tsOld != Instant.EPOCH && tsNew != Instant.EPOCH && !tsOld.isBefore(tsNew)) {
546+
final String errorMsg = "Last partition timestamp of indexed files " + tsOld.getEpochSecond()
547+
+ " is after last partition of non-indexed files " + tsNew.getEpochSecond();
548+
LOGGER.error(errorMsg);
549+
throw new IllegalStateException(errorMsg);
550+
}
542551
// if there are new partitions in this update, let index delete some in-mem delta caches that is old
543552
if (tsNew != Instant.EPOCH) {
544553
tsNew = tsNew.minusSeconds(fileUtils.lookbackGracePeriod());
@@ -594,15 +603,21 @@ private OptOutStoreSnapshot updateIndexInternal(IndexUpdateContext iuc) {
594603
try {
595604
if (numPartitions == 0) {
596605
// if update doesn't have a new partition, simply update heap with new log data
597-
assert iuc.getDeltasToRemove().size() == 0;
606+
if (!iuc.getDeltasToRemove().isEmpty()) {
607+
final String errorMsg = "Invalid number of Deltas to remove=" + iuc.getDeltasToRemove().size()
608+
+ " when there are 0 new partitions to index";
609+
LOGGER.error(errorMsg);
610+
throw new IllegalStateException(errorMsg);
611+
}
598612
return this.processDeltas(iuc);
599613
} else if (numPartitions > 1) {
600-
// should not load more than 1 partition at a time, unless during service bootstrap
601-
assert this.iteration == 0;
614+
if (this.iteration != 0) {
615+
final String errorMsg = "Should not load more than 1 partition at a time, unless during service bootstrap. Current iteration " + this.iteration;
616+
// Leaving this as a warning as this condition is true in production
617+
LOGGER.warn(errorMsg);
618+
}
602619
return this.processPartitions(iuc);
603620
} else {
604-
// array size cannot be a negative value
605-
assert numPartitions == 1;
606621
return this.processPartitions(iuc);
607622
}
608623
} finally {
@@ -628,7 +643,11 @@ private OptOutStoreSnapshot processDeltasImpl(IndexUpdateContext iuc) {
628643
// this is thread-safe, as heap is not being used
629644
// and bloomfilter can tolerate false positive
630645
for (byte[] data : loadedData) {
631-
assert data.length != 0;
646+
if (data.length == 0) {
647+
final String errorMsg = "Loaded delta file has 0 size";
648+
LOGGER.error(errorMsg);
649+
throw new IllegalStateException(errorMsg);
650+
}
632651

633652
OptOutCollection newLog = new OptOutCollection(data);
634653
this.heap.add(newLog);
@@ -679,7 +698,11 @@ private OptOutStoreSnapshot processPartitionsImpl(IndexUpdateContext iuc) {
679698
}
680699
for (String key : sortedPartitionFiles) {
681700
byte[] data = iuc.loadedPartitions.get(key);
682-
assert data.length != 0;
701+
if (data.length == 0) {
702+
final String errorMsg = "Loaded partition file has 0 size";
703+
LOGGER.error(errorMsg);
704+
throw new IllegalStateException(errorMsg);
705+
}
683706
newPartitions[snapIndex++] = new OptOutPartition(data);
684707
}
685708

src/main/java/com/uid2/operator/util/Tuple.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
package com.uid2.operator.util;
22

3+
import java.util.Objects;
4+
35
public class Tuple {
46
public static class Tuple2<T1, T2> {
57
private final T1 item1;
68
private final T2 item2;
79

810
public Tuple2(T1 item1, T2 item2) {
9-
assert item1 != null;
10-
assert item2 != null;
11+
Objects.requireNonNull(item1);
12+
Objects.requireNonNull(item2);
1113

1214
this.item1 = item1;
1315
this.item2 = item2;
@@ -34,9 +36,9 @@ public static class Tuple3<T1, T2, T3> {
3436
private final T3 item3;
3537

3638
public Tuple3(T1 item1, T2 item2, T3 item3) {
37-
assert item1 != null;
38-
assert item2 != null;
39-
assert item3 != null;
39+
Objects.requireNonNull(item1);
40+
Objects.requireNonNull(item2);
41+
Objects.requireNonNull(item3);
4042

4143
this.item1 = item1;
4244
this.item2 = item2;

src/main/java/com/uid2/operator/vertx/UIDOperatorVerticle.java

Lines changed: 25 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
import io.vertx.core.json.JsonArray;
4646
import io.vertx.core.json.JsonObject;
4747
import io.vertx.ext.web.AllowForwardHeaders;
48-
import io.vertx.ext.web.Route;
4948
import io.vertx.ext.web.Router;
5049
import io.vertx.ext.web.RoutingContext;
5150
import io.vertx.ext.web.handler.BodyHandler;
@@ -129,6 +128,10 @@ public class UIDOperatorVerticle extends AbstractVerticle {
129128
//"Android" is from https://github.com/IABTechLab/uid2-android-sdk/blob/ff93ebf597f5de7d440a84f7015a334ba4138ede/sdk/src/main/java/com/uid2/UID2Client.kt#L46
130129
//"ios"/"tvos" is from https://github.com/IABTechLab/uid2-ios-sdk/blob/91c290d29a7093cfc209eca493d1fee80c17e16a/Sources/UID2/UID2Client.swift#L36-L38
131130
private final static List<String> SUPPORTED_IN_APP = Arrays.asList("Android", "ios", "tvos");
131+
132+
private static final String ERROR_INVALID_INPUT_WITH_PHONE_SUPPORT = "Required Parameter Missing: exactly one of [email, email_hash, phone, phone_hash] must be specified";
133+
private static final String ERROR_INVALID_INPUT_EMAIL_MISSING = "Required Parameter Missing: exactly one of email or email_hash must be specified";
134+
private static final String ERROR_INVALID_INPUT_EMAIL_TWICE = "Only one of email or email_hash can be specified";
132135
public final static String ORIGIN_HEADER = "Origin";
133136

134137
public UIDOperatorVerticle(JsonObject config,
@@ -450,7 +453,7 @@ else if(emailHash != null) {
450453
input = InputUtil.normalizePhoneHash(phoneHash);
451454
}
452455

453-
if (!checkForInvalidTokenInput(input, rc)) {
456+
if (!isTokenInputValid(input, rc)) {
454457
return;
455458
}
456459

@@ -869,7 +872,7 @@ private void handleTokenRefreshV2(RoutingContext rc) {
869872
private void handleTokenValidateV1(RoutingContext rc) {
870873
try {
871874
final InputUtil.InputVal input = this.phoneSupport ? getTokenInputV1(rc) : getTokenInput(rc);
872-
if (!checkForInvalidTokenInput(input, rc)) {
875+
if (!isTokenInputValid(input, rc)) {
873876
return;
874877
}
875878
if ((Arrays.equals(ValidateIdentityForEmailHash, input.getIdentityInput()) && input.getIdentityType() == IdentityType.Email)
@@ -900,7 +903,7 @@ private void handleTokenValidateV2(RoutingContext rc) {
900903
final JsonObject req = (JsonObject) rc.data().get("request");
901904

902905
final InputUtil.InputVal input = getTokenInputV2(req);
903-
if (!checkForInvalidTokenInput(input, rc)) {
906+
if (!isTokenInputValid(input, rc)) {
904907
return;
905908
}
906909
if ((input.getIdentityType() == IdentityType.Email && Arrays.equals(ValidateIdentityForEmailHash, input.getIdentityInput()))
@@ -932,17 +935,13 @@ private void handleTokenGenerateV1(RoutingContext rc) {
932935
try {
933936
final InputUtil.InputVal input = this.phoneSupport ? this.getTokenInputV1(rc) : this.getTokenInput(rc);
934937
platformType = getPlatformType(rc);
935-
if (!checkForInvalidTokenInput(input, rc)) {
936-
return;
937-
} else {
938+
if (isTokenInputValid(input, rc)) {
938939
final IdentityTokens t = this.idService.generateIdentity(
939940
new IdentityRequest(
940941
new PublisherIdentity(siteId, 0, 0),
941942
input.toUserIdentity(this.identityScope, 1, Instant.now()),
942943
OptoutCheckPolicy.defaultPolicy()));
943944

944-
//Integer.parseInt(rc.queryParam("privacy_bits").get(0))));
945-
946945
ResponseUtil.Success(rc, toJsonV1(t));
947946
recordTokenResponseStats(siteId, TokenResponseStatsCollector.Endpoint.GenerateV1, TokenResponseStatsCollector.ResponseStatus.Success, siteProvider, t.getAdvertisingTokenVersion(), platformType);
948947
}
@@ -959,9 +958,7 @@ private void handleTokenGenerateV2(RoutingContext rc) {
959958
platformType = getPlatformType(rc);
960959

961960
final InputUtil.InputVal input = this.getTokenInputV2(req);
962-
if (!checkForInvalidTokenInput(input, rc)) {
963-
return;
964-
} else {
961+
if (isTokenInputValid(input, rc)) {
965962
final String apiContact = getApiContact(rc);
966963

967964
switch (validateUserConsent(req)) {
@@ -978,8 +975,9 @@ private void handleTokenGenerateV2(RoutingContext rc) {
978975
break;
979976
}
980977
default: {
981-
assert false : "Please update UIDOperatorVerticle.handleTokenGenerateV2 when changing UserConsentStatus";
982-
break;
978+
final String errorMsg = "Please update UIDOperatorVerticle.handleTokenGenerateV2 when changing UserConsentStatus";
979+
LOGGER.error(errorMsg);
980+
throw new IllegalStateException(errorMsg);
983981
}
984982
}
985983

@@ -1037,7 +1035,7 @@ private void handleTokenGenerate(RoutingContext rc) {
10371035
final InputUtil.InputVal input = this.getTokenInput(rc);
10381036
Integer siteId = null;
10391037
if (input == null) {
1040-
SendClientErrorResponseAndRecordStats(ResponseStatus.ClientError, 400, rc, "Required Parameter Missing: exactly one of email or email_hash must be specified", siteId, TokenResponseStatsCollector.Endpoint.GenerateV0, TokenResponseStatsCollector.ResponseStatus.BadPayload, siteProvider, TokenResponseStatsCollector.PlatformType.Other);
1038+
SendClientErrorResponseAndRecordStats(ResponseStatus.ClientError, 400, rc, ERROR_INVALID_INPUT_EMAIL_MISSING, siteId, TokenResponseStatsCollector.Endpoint.GenerateV0, TokenResponseStatsCollector.ResponseStatus.BadPayload, siteProvider, TokenResponseStatsCollector.PlatformType.Other);
10411039
return;
10421040
}
10431041
else if (!input.isValid()) {
@@ -1053,8 +1051,6 @@ else if (!input.isValid()) {
10531051
input.toUserIdentity(this.identityScope, 1, Instant.now()),
10541052
OptoutCheckPolicy.defaultPolicy()));
10551053

1056-
//Integer.parseInt(rc.queryParam("privacy_bits").get(0))));
1057-
10581054
recordTokenResponseStats(siteId, TokenResponseStatsCollector.Endpoint.GenerateV0, TokenResponseStatsCollector.ResponseStatus.Success, siteProvider, t.getAdvertisingTokenVersion(), TokenResponseStatsCollector.PlatformType.Other);
10591055
sendJsonResponse(rc, toJson(t));
10601056

@@ -1234,7 +1230,7 @@ private void handleBucketsV2(RoutingContext rc) {
12341230

12351231
private void handleIdentityMapV1(RoutingContext rc) {
12361232
final InputUtil.InputVal input = this.phoneSupport ? this.getTokenInputV1(rc) : this.getTokenInput(rc);
1237-
if (!checkForInvalidTokenInput(input, rc)) {
1233+
if (!isTokenInputValid(input, rc)) {
12381234
return;
12391235
}
12401236
try {
@@ -1254,13 +1250,7 @@ private void handleIdentityMap(RoutingContext rc) {
12541250
final InputUtil.InputVal input = this.getTokenInput(rc);
12551251

12561252
try {
1257-
if (input == null) {
1258-
ResponseUtil.ClientError(rc, "Required Parameter Missing: exactly one of email or email_hash must be specified");
1259-
}
1260-
else if (!input.isValid()) {
1261-
ResponseUtil.ClientError(rc, "Invalid email or email_hash");
1262-
}
1263-
else {
1253+
if (isTokenInputValid(input, rc)) {
12641254
final Instant now = Instant.now();
12651255
final MappedIdentity mappedIdentity = this.idService.map(input.toUserIdentity(this.identityScope, 0, now), now);
12661256
rc.response().end(EncodingUtils.toBase64String(mappedIdentity.advertisingId));
@@ -1363,9 +1353,9 @@ private InputUtil.InputVal getTokenInputV1(RoutingContext rc) {
13631353
return null;
13641354
}
13651355

1366-
private boolean checkForInvalidTokenInput(InputUtil.InputVal input, RoutingContext rc) {
1356+
private boolean isTokenInputValid(InputUtil.InputVal input, RoutingContext rc) {
13671357
if (input == null) {
1368-
String message = this.phoneSupport ? "Required Parameter Missing: exactly one of [email, email_hash, phone, phone_hash] must be specified" : "Required Parameter Missing: exactly one of email or email_hash must be specified";
1358+
String message = this.phoneSupport ? ERROR_INVALID_INPUT_WITH_PHONE_SUPPORT : ERROR_INVALID_INPUT_EMAIL_MISSING;
13691359
ResponseUtil.ClientError(rc, message);
13701360
return false;
13711361
} else if (!input.isValid()) {
@@ -1381,11 +1371,11 @@ private InputUtil.InputVal[] getIdentityBulkInput(RoutingContext rc) {
13811371
final JsonArray emailHashes = obj.getJsonArray("email_hash");
13821372
// FIXME TODO. Avoid Double Iteration. Turn to a decorator pattern
13831373
if (emails == null && emailHashes == null) {
1384-
ResponseUtil.ClientError(rc, "Exactly one of email or email_hash must be specified");
1374+
ResponseUtil.ClientError(rc, ERROR_INVALID_INPUT_EMAIL_MISSING);
13851375
return null;
13861376
} else if (emails != null && !emails.isEmpty()) {
13871377
if (emailHashes != null && !emailHashes.isEmpty()) {
1388-
ResponseUtil.ClientError(rc, "Only one of email or email_hash can be specified");
1378+
ResponseUtil.ClientError(rc, ERROR_INVALID_INPUT_EMAIL_TWICE);
13891379
return null;
13901380
}
13911381
return createInputList(emails, false);
@@ -1398,7 +1388,7 @@ private InputUtil.InputVal[] getIdentityBulkInput(RoutingContext rc) {
13981388
private InputUtil.InputVal[] getIdentityBulkInputV1(RoutingContext rc) {
13991389
final JsonObject obj = rc.body().asJsonObject();
14001390
if(obj.isEmpty()) {
1401-
ResponseUtil.ClientError(rc, "Exactly one of [email, email_hash, phone, phone_hash] must be specified");
1391+
ResponseUtil.ClientError(rc, ERROR_INVALID_INPUT_WITH_PHONE_SUPPORT);
14021392
return null;
14031393
}
14041394
final JsonArray emails = JsonParseUtils.parseArray(obj, "email", rc);
@@ -1430,7 +1420,7 @@ private InputUtil.InputVal[] getIdentityBulkInputV1(RoutingContext rc) {
14301420
}
14311421

14321422
if (validInputs == 0 || nonEmptyInputs > 1) {
1433-
ResponseUtil.ClientError(rc, "Exactly one of [email, email_hash, phone, phone_hash] must be specified");
1423+
ResponseUtil.ClientError(rc, ERROR_INVALID_INPUT_WITH_PHONE_SUPPORT);
14341424
return null;
14351425
}
14361426

@@ -1511,9 +1501,9 @@ private void handleIdentityMapV2(RoutingContext rc) {
15111501
final InputUtil.InputVal[] inputList = getIdentityMapV2Input(rc);
15121502
if (inputList == null) {
15131503
if (this.phoneSupport)
1514-
ResponseUtil.ClientError(rc, "Exactly one of [email, email_hash, phone, phone_hash] must be specified");
1504+
ResponseUtil.ClientError(rc, ERROR_INVALID_INPUT_WITH_PHONE_SUPPORT);
15151505
else
1516-
ResponseUtil.ClientError(rc, "Required Parameter Missing: exactly one of email or email_hash must be specified");
1506+
ResponseUtil.ClientError(rc, ERROR_INVALID_INPUT_EMAIL_MISSING);
15171507
return;
15181508
}
15191509

@@ -1579,11 +1569,11 @@ private void handleIdentityMapBatch(RoutingContext rc) {
15791569
final JsonArray emails = obj.getJsonArray("email");
15801570
final JsonArray emailHashes = obj.getJsonArray("email_hash");
15811571
if (emails == null && emailHashes == null) {
1582-
ResponseUtil.ClientError(rc, "Exactly one of email or email_hash must be specified");
1572+
ResponseUtil.ClientError(rc, ERROR_INVALID_INPUT_EMAIL_MISSING);
15831573
return;
15841574
} else if (emails != null && !emails.isEmpty()) {
15851575
if (emailHashes != null && !emailHashes.isEmpty()) {
1586-
ResponseUtil.ClientError(rc, "Only one of email or email_hash can be specified");
1576+
ResponseUtil.ClientError(rc, ERROR_INVALID_INPUT_EMAIL_TWICE);
15871577
return;
15881578
}
15891579
inputList = createInputList(emails, false);

0 commit comments

Comments
 (0)