@Test public void updateInternal_removeValue_notRemoteCapable() { UpdateResult result = FeatureFlags.updateInternal(mapOf(A, true), mapOf(A, true), mapOf(A, true), setOf(), setOf(), setOf()); assertEquals(mapOf(A, true), result.getMemory()); assertEquals(mapOf(), result.getDisk()); assertTrue(result.getMemoryChanges().isEmpty()); }
@VisibleForTesting static @NonNull UpdateResult updateInternal(@NonNull Map<String, Object> remote, @NonNull Map<String, Object> localMemory, @NonNull Map<String, Object> localDisk, @NonNull Set<String> remoteCapable, @NonNull Set<String> hotSwap, @NonNull Set<String> sticky) { Map<String, Object> newMemory = new TreeMap<>(localMemory); Map<String, Object> newDisk = new TreeMap<>(localDisk); Set<String> allKeys = new HashSet<>(); allKeys.addAll(remote.keySet()); allKeys.addAll(localDisk.keySet()); allKeys.addAll(localMemory.keySet()); Stream.of(allKeys) .filter(remoteCapable::contains) .forEach(key -> { Object remoteValue = remote.get(key); Object diskValue = localDisk.get(key); Object newValue = remoteValue; if (newValue != null && diskValue != null && newValue.getClass() != diskValue.getClass()) { Log.w(TAG, "Type mismatch! key: " + key); newDisk.remove(key); if (hotSwap.contains(key)) { newMemory.remove(key); } return; } if (sticky.contains(key) && (newValue instanceof Boolean || diskValue instanceof Boolean)) { newValue = diskValue == Boolean.TRUE ? Boolean.TRUE : newValue; } else if (sticky.contains(key)) { Log.w(TAG, "Tried to make a non-boolean sticky! Ignoring. (key: " + key + ")"); } if (newValue != null) { newDisk.put(key, newValue); } else { newDisk.remove(key); } if (hotSwap.contains(key)) { if (newValue != null) { newMemory.put(key, newValue); } else { newMemory.remove(key); } } }); Stream.of(allKeys) .filterNot(remoteCapable::contains) .filterNot(key -> sticky.contains(key) && localDisk.get(key) == Boolean.TRUE) .forEach(key -> { newDisk.remove(key); if (hotSwap.contains(key)) { newMemory.remove(key); } }); return new UpdateResult(newMemory, newDisk, computeChanges(localMemory, newMemory)); }
FeatureFlags { @VisibleForTesting static @NonNull UpdateResult updateInternal(@NonNull Map<String, Object> remote, @NonNull Map<String, Object> localMemory, @NonNull Map<String, Object> localDisk, @NonNull Set<String> remoteCapable, @NonNull Set<String> hotSwap, @NonNull Set<String> sticky) { Map<String, Object> newMemory = new TreeMap<>(localMemory); Map<String, Object> newDisk = new TreeMap<>(localDisk); Set<String> allKeys = new HashSet<>(); allKeys.addAll(remote.keySet()); allKeys.addAll(localDisk.keySet()); allKeys.addAll(localMemory.keySet()); Stream.of(allKeys) .filter(remoteCapable::contains) .forEach(key -> { Object remoteValue = remote.get(key); Object diskValue = localDisk.get(key); Object newValue = remoteValue; if (newValue != null && diskValue != null && newValue.getClass() != diskValue.getClass()) { Log.w(TAG, "Type mismatch! key: " + key); newDisk.remove(key); if (hotSwap.contains(key)) { newMemory.remove(key); } return; } if (sticky.contains(key) && (newValue instanceof Boolean || diskValue instanceof Boolean)) { newValue = diskValue == Boolean.TRUE ? Boolean.TRUE : newValue; } else if (sticky.contains(key)) { Log.w(TAG, "Tried to make a non-boolean sticky! Ignoring. (key: " + key + ")"); } if (newValue != null) { newDisk.put(key, newValue); } else { newDisk.remove(key); } if (hotSwap.contains(key)) { if (newValue != null) { newMemory.put(key, newValue); } else { newMemory.remove(key); } } }); Stream.of(allKeys) .filterNot(remoteCapable::contains) .filterNot(key -> sticky.contains(key) && localDisk.get(key) == Boolean.TRUE) .forEach(key -> { newDisk.remove(key); if (hotSwap.contains(key)) { newMemory.remove(key); } }); return new UpdateResult(newMemory, newDisk, computeChanges(localMemory, newMemory)); } }
FeatureFlags { @VisibleForTesting static @NonNull UpdateResult updateInternal(@NonNull Map<String, Object> remote, @NonNull Map<String, Object> localMemory, @NonNull Map<String, Object> localDisk, @NonNull Set<String> remoteCapable, @NonNull Set<String> hotSwap, @NonNull Set<String> sticky) { Map<String, Object> newMemory = new TreeMap<>(localMemory); Map<String, Object> newDisk = new TreeMap<>(localDisk); Set<String> allKeys = new HashSet<>(); allKeys.addAll(remote.keySet()); allKeys.addAll(localDisk.keySet()); allKeys.addAll(localMemory.keySet()); Stream.of(allKeys) .filter(remoteCapable::contains) .forEach(key -> { Object remoteValue = remote.get(key); Object diskValue = localDisk.get(key); Object newValue = remoteValue; if (newValue != null && diskValue != null && newValue.getClass() != diskValue.getClass()) { Log.w(TAG, "Type mismatch! key: " + key); newDisk.remove(key); if (hotSwap.contains(key)) { newMemory.remove(key); } return; } if (sticky.contains(key) && (newValue instanceof Boolean || diskValue instanceof Boolean)) { newValue = diskValue == Boolean.TRUE ? Boolean.TRUE : newValue; } else if (sticky.contains(key)) { Log.w(TAG, "Tried to make a non-boolean sticky! Ignoring. (key: " + key + ")"); } if (newValue != null) { newDisk.put(key, newValue); } else { newDisk.remove(key); } if (hotSwap.contains(key)) { if (newValue != null) { newMemory.put(key, newValue); } else { newMemory.remove(key); } } }); Stream.of(allKeys) .filterNot(remoteCapable::contains) .filterNot(key -> sticky.contains(key) && localDisk.get(key) == Boolean.TRUE) .forEach(key -> { newDisk.remove(key); if (hotSwap.contains(key)) { newMemory.remove(key); } }); return new UpdateResult(newMemory, newDisk, computeChanges(localMemory, newMemory)); } private  FeatureFlags(); }
FeatureFlags { @VisibleForTesting static @NonNull UpdateResult updateInternal(@NonNull Map<String, Object> remote, @NonNull Map<String, Object> localMemory, @NonNull Map<String, Object> localDisk, @NonNull Set<String> remoteCapable, @NonNull Set<String> hotSwap, @NonNull Set<String> sticky) { Map<String, Object> newMemory = new TreeMap<>(localMemory); Map<String, Object> newDisk = new TreeMap<>(localDisk); Set<String> allKeys = new HashSet<>(); allKeys.addAll(remote.keySet()); allKeys.addAll(localDisk.keySet()); allKeys.addAll(localMemory.keySet()); Stream.of(allKeys) .filter(remoteCapable::contains) .forEach(key -> { Object remoteValue = remote.get(key); Object diskValue = localDisk.get(key); Object newValue = remoteValue; if (newValue != null && diskValue != null && newValue.getClass() != diskValue.getClass()) { Log.w(TAG, "Type mismatch! key: " + key); newDisk.remove(key); if (hotSwap.contains(key)) { newMemory.remove(key); } return; } if (sticky.contains(key) && (newValue instanceof Boolean || diskValue instanceof Boolean)) { newValue = diskValue == Boolean.TRUE ? Boolean.TRUE : newValue; } else if (sticky.contains(key)) { Log.w(TAG, "Tried to make a non-boolean sticky! Ignoring. (key: " + key + ")"); } if (newValue != null) { newDisk.put(key, newValue); } else { newDisk.remove(key); } if (hotSwap.contains(key)) { if (newValue != null) { newMemory.put(key, newValue); } else { newMemory.remove(key); } } }); Stream.of(allKeys) .filterNot(remoteCapable::contains) .filterNot(key -> sticky.contains(key) && localDisk.get(key) == Boolean.TRUE) .forEach(key -> { newDisk.remove(key); if (hotSwap.contains(key)) { newMemory.remove(key); } }); return new UpdateResult(newMemory, newDisk, computeChanges(localMemory, newMemory)); } private  FeatureFlags(); static synchronized void init(); static synchronized void refreshIfNecessary(); static synchronized void update(@NonNull Map<String, Object> config); static synchronized boolean usernames(); static boolean groupsV2create(); static boolean groupsV2manageGroupLinks(); static int gv2GroupCapacity(); static GroupJoinStatus clientLocalGroupJoinStatus(); static boolean internalUser(); static boolean mentions(); static boolean verifyV2(); static String clientExpiration(); static String researchMegaphone(); static boolean phoneNumberPrivacy(); static synchronized @NonNull Map<String, Object> getMemoryValues(); static synchronized @NonNull Map<String, Object> getDiskValues(); static synchronized @NonNull Map<String, Object> getPendingDiskValues(); static synchronized @NonNull Map<String, Object> getForcedValues(); }
FeatureFlags { @VisibleForTesting static @NonNull UpdateResult updateInternal(@NonNull Map<String, Object> remote, @NonNull Map<String, Object> localMemory, @NonNull Map<String, Object> localDisk, @NonNull Set<String> remoteCapable, @NonNull Set<String> hotSwap, @NonNull Set<String> sticky) { Map<String, Object> newMemory = new TreeMap<>(localMemory); Map<String, Object> newDisk = new TreeMap<>(localDisk); Set<String> allKeys = new HashSet<>(); allKeys.addAll(remote.keySet()); allKeys.addAll(localDisk.keySet()); allKeys.addAll(localMemory.keySet()); Stream.of(allKeys) .filter(remoteCapable::contains) .forEach(key -> { Object remoteValue = remote.get(key); Object diskValue = localDisk.get(key); Object newValue = remoteValue; if (newValue != null && diskValue != null && newValue.getClass() != diskValue.getClass()) { Log.w(TAG, "Type mismatch! key: " + key); newDisk.remove(key); if (hotSwap.contains(key)) { newMemory.remove(key); } return; } if (sticky.contains(key) && (newValue instanceof Boolean || diskValue instanceof Boolean)) { newValue = diskValue == Boolean.TRUE ? Boolean.TRUE : newValue; } else if (sticky.contains(key)) { Log.w(TAG, "Tried to make a non-boolean sticky! Ignoring. (key: " + key + ")"); } if (newValue != null) { newDisk.put(key, newValue); } else { newDisk.remove(key); } if (hotSwap.contains(key)) { if (newValue != null) { newMemory.put(key, newValue); } else { newMemory.remove(key); } } }); Stream.of(allKeys) .filterNot(remoteCapable::contains) .filterNot(key -> sticky.contains(key) && localDisk.get(key) == Boolean.TRUE) .forEach(key -> { newDisk.remove(key); if (hotSwap.contains(key)) { newMemory.remove(key); } }); return new UpdateResult(newMemory, newDisk, computeChanges(localMemory, newMemory)); } private  FeatureFlags(); static synchronized void init(); static synchronized void refreshIfNecessary(); static synchronized void update(@NonNull Map<String, Object> config); static synchronized boolean usernames(); static boolean groupsV2create(); static boolean groupsV2manageGroupLinks(); static int gv2GroupCapacity(); static GroupJoinStatus clientLocalGroupJoinStatus(); static boolean internalUser(); static boolean mentions(); static boolean verifyV2(); static String clientExpiration(); static String researchMegaphone(); static boolean phoneNumberPrivacy(); static synchronized @NonNull Map<String, Object> getMemoryValues(); static synchronized @NonNull Map<String, Object> getDiskValues(); static synchronized @NonNull Map<String, Object> getPendingDiskValues(); static synchronized @NonNull Map<String, Object> getForcedValues(); static final String RESEARCH_MEGAPHONE_1; }