Merge "Implement storage files in Java" into main
This commit is contained in:
@@ -98,6 +98,10 @@
|
|||||||
{
|
{
|
||||||
// aconfig_storage file cpp integration tests
|
// aconfig_storage file cpp integration tests
|
||||||
"name": "aconfig_storage_file.test.cpp"
|
"name": "aconfig_storage_file.test.cpp"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// aconfig_storage file java integration tests
|
||||||
|
"name": "aconfig_storage_file.test.java"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"postsubmit": [
|
"postsubmit": [
|
||||||
|
@@ -137,3 +137,12 @@ cc_library {
|
|||||||
min_sdk_version: "29",
|
min_sdk_version: "29",
|
||||||
double_loadable: true,
|
double_loadable: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// storage file parse api java cc_library
|
||||||
|
java_library {
|
||||||
|
name: "aconfig_storage_file_java",
|
||||||
|
srcs: [
|
||||||
|
"srcs/**/*.java",
|
||||||
|
],
|
||||||
|
sdk_version: "core_current",
|
||||||
|
}
|
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.aconfig.storage;
|
||||||
|
|
||||||
|
public class AconfigStorageException extends RuntimeException {
|
||||||
|
public AconfigStorageException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AconfigStorageException(String msg, Throwable cause) {
|
||||||
|
super(msg, cause);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.aconfig.storage;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public class ByteBufferReader {
|
||||||
|
|
||||||
|
private ByteBuffer mByteBuffer;
|
||||||
|
|
||||||
|
public ByteBufferReader(ByteBuffer byteBuffer) {
|
||||||
|
this.mByteBuffer = byteBuffer;
|
||||||
|
this.mByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int readByte() {
|
||||||
|
return Byte.toUnsignedInt(mByteBuffer.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
public int readShort() {
|
||||||
|
return Short.toUnsignedInt(mByteBuffer.getShort());
|
||||||
|
}
|
||||||
|
|
||||||
|
public int readInt() {
|
||||||
|
return this.mByteBuffer.getInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String readString() {
|
||||||
|
int length = readInt();
|
||||||
|
byte[] bytes = new byte[length];
|
||||||
|
mByteBuffer.get(bytes, 0, length);
|
||||||
|
return new String(bytes, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void position(int newPosition) {
|
||||||
|
mByteBuffer.position(newPosition);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.aconfig.storage;
|
||||||
|
|
||||||
|
public enum FileType {
|
||||||
|
PACKAGE_MAP(0),
|
||||||
|
FLAG_MAP(1),
|
||||||
|
FLAG_VAL(2),
|
||||||
|
FLAG_INFO(3);
|
||||||
|
|
||||||
|
public final int type;
|
||||||
|
|
||||||
|
FileType(int type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FileType fromInt(int index) {
|
||||||
|
switch (index) {
|
||||||
|
case 0:
|
||||||
|
return PACKAGE_MAP;
|
||||||
|
case 1:
|
||||||
|
return FLAG_MAP;
|
||||||
|
case 2:
|
||||||
|
return FLAG_VAL;
|
||||||
|
case 3:
|
||||||
|
return FLAG_INFO;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,174 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.aconfig.storage;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class FlagTable {
|
||||||
|
|
||||||
|
private Header mHeader;
|
||||||
|
private Map<String, Node> mNodeMap;
|
||||||
|
|
||||||
|
public static FlagTable fromBytes(ByteBuffer bytes) {
|
||||||
|
FlagTable flagTable = new FlagTable();
|
||||||
|
ByteBufferReader reader = new ByteBufferReader(bytes);
|
||||||
|
Header header = Header.fromBytes(reader);
|
||||||
|
flagTable.mHeader = header;
|
||||||
|
flagTable.mNodeMap = new HashMap(TableUtils.getTableSize(header.mNumFlags));
|
||||||
|
reader.position(header.mNodeOffset);
|
||||||
|
for (int i = 0; i < header.mNumFlags; i++) {
|
||||||
|
Node node = Node.fromBytes(reader);
|
||||||
|
flagTable.mNodeMap.put(makeKey(node.mPackageId, node.mFlagName), node);
|
||||||
|
}
|
||||||
|
return flagTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node get(int packageId, String flagName) {
|
||||||
|
return mNodeMap.get(makeKey(packageId, flagName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Header getHeader() {
|
||||||
|
return mHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String makeKey(int packageId, String flagName) {
|
||||||
|
StringBuilder ret = new StringBuilder();
|
||||||
|
return ret.append(packageId).append('/').append(flagName).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Header {
|
||||||
|
|
||||||
|
private int mVersion;
|
||||||
|
private String mContainer;
|
||||||
|
private FileType mFileType;
|
||||||
|
private int mFileSize;
|
||||||
|
private int mNumFlags;
|
||||||
|
private int mBucketOffset;
|
||||||
|
private int mNodeOffset;
|
||||||
|
|
||||||
|
public static Header fromBytes(ByteBufferReader reader) {
|
||||||
|
Header header = new Header();
|
||||||
|
header.mVersion = reader.readInt();
|
||||||
|
header.mContainer = reader.readString();
|
||||||
|
header.mFileType = FileType.fromInt(reader.readByte());
|
||||||
|
header.mFileSize = reader.readInt();
|
||||||
|
header.mNumFlags = reader.readInt();
|
||||||
|
header.mBucketOffset = reader.readInt();
|
||||||
|
header.mNodeOffset = reader.readInt();
|
||||||
|
|
||||||
|
if (header.mFileType != FileType.FLAG_MAP) {
|
||||||
|
throw new AconfigStorageException("binary file is not a flag map");
|
||||||
|
}
|
||||||
|
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVersion() {
|
||||||
|
return mVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContainer() {
|
||||||
|
return mContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileType getFileType() {
|
||||||
|
return mFileType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFileSize() {
|
||||||
|
return mFileSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumFlags() {
|
||||||
|
return mNumFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBucketOffset() {
|
||||||
|
return mBucketOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNodeOffset() {
|
||||||
|
return mNodeOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Node {
|
||||||
|
|
||||||
|
private String mFlagName;
|
||||||
|
private FlagType mFlagType;
|
||||||
|
private int mPackageId;
|
||||||
|
private int mFlagIndex;
|
||||||
|
private int mNextOffset;
|
||||||
|
|
||||||
|
public static Node fromBytes(ByteBufferReader reader) {
|
||||||
|
Node node = new Node();
|
||||||
|
node.mPackageId = reader.readInt();
|
||||||
|
node.mFlagName = reader.readString();
|
||||||
|
node.mFlagType = FlagType.fromInt(reader.readShort());
|
||||||
|
node.mFlagIndex = reader.readShort();
|
||||||
|
node.mNextOffset = reader.readInt();
|
||||||
|
node.mNextOffset = node.mNextOffset == 0 ? -1 : node.mNextOffset;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(mFlagName, mFlagType, mPackageId, mFlagIndex, mNextOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj == null || !(obj instanceof Node)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node other = (Node) obj;
|
||||||
|
return Objects.equals(mFlagName, other.mFlagName)
|
||||||
|
&& Objects.equals(mFlagType, other.mFlagType)
|
||||||
|
&& mPackageId == other.mPackageId
|
||||||
|
&& mFlagIndex == other.mFlagIndex
|
||||||
|
&& mNextOffset == other.mNextOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFlagName() {
|
||||||
|
return mFlagName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FlagType getFlagType() {
|
||||||
|
return mFlagType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPackageId() {
|
||||||
|
return mPackageId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFlagIndex() {
|
||||||
|
return mFlagIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNextOffset() {
|
||||||
|
return mNextOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.aconfig.storage;
|
||||||
|
|
||||||
|
public enum FlagType {
|
||||||
|
ReadWriteBoolean (0),
|
||||||
|
ReadOnlyBoolean(1),
|
||||||
|
FixedReadOnlyBoolean(2);
|
||||||
|
|
||||||
|
public final int type;
|
||||||
|
|
||||||
|
FlagType(int type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FlagType fromInt(int index) {
|
||||||
|
switch (index) {
|
||||||
|
case 0:
|
||||||
|
return ReadWriteBoolean;
|
||||||
|
case 1:
|
||||||
|
return ReadOnlyBoolean;
|
||||||
|
case 2:
|
||||||
|
return FixedReadOnlyBoolean;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.aconfig.storage;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class FlagValueList {
|
||||||
|
|
||||||
|
private Header mHeader;
|
||||||
|
private List<Boolean> mList;
|
||||||
|
|
||||||
|
private int mSize;
|
||||||
|
|
||||||
|
public static FlagValueList fromBytes(ByteBuffer bytes) {
|
||||||
|
FlagValueList flagValueList = new FlagValueList();
|
||||||
|
ByteBufferReader reader = new ByteBufferReader(bytes);
|
||||||
|
Header header = Header.fromBytes(reader);
|
||||||
|
flagValueList.mHeader = header;
|
||||||
|
flagValueList.mList = new ArrayList(header.mNumFlags);
|
||||||
|
reader.position(header.mBooleanValueOffset);
|
||||||
|
for (int i = 0; i < header.mNumFlags; i++) {
|
||||||
|
boolean val = reader.readByte() == 1;
|
||||||
|
flagValueList.mList.add(val);
|
||||||
|
}
|
||||||
|
flagValueList.mSize = flagValueList.mList.size();
|
||||||
|
return flagValueList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean get(int index) {
|
||||||
|
return mList.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Header getHeader() {
|
||||||
|
return mHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return mSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Header {
|
||||||
|
|
||||||
|
private int mVersion;
|
||||||
|
private String mContainer;
|
||||||
|
private FileType mFileType;
|
||||||
|
private int mFileSize;
|
||||||
|
private int mNumFlags;
|
||||||
|
private int mBooleanValueOffset;
|
||||||
|
|
||||||
|
public static Header fromBytes(ByteBufferReader reader) {
|
||||||
|
Header header = new Header();
|
||||||
|
header.mVersion = reader.readInt();
|
||||||
|
header.mContainer = reader.readString();
|
||||||
|
header.mFileType = FileType.fromInt(reader.readByte());
|
||||||
|
header.mFileSize = reader.readInt();
|
||||||
|
header.mNumFlags = reader.readInt();
|
||||||
|
header.mBooleanValueOffset = reader.readInt();
|
||||||
|
|
||||||
|
if (header.mFileType != FileType.FLAG_VAL) {
|
||||||
|
throw new AconfigStorageException("binary file is not a flag value file");
|
||||||
|
}
|
||||||
|
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVersion() {
|
||||||
|
return mVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContainer() {
|
||||||
|
return mContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileType getFileType() {
|
||||||
|
return mFileType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFileSize() {
|
||||||
|
return mFileSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumFlags() {
|
||||||
|
return mNumFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBooleanValueOffset() {
|
||||||
|
return mBooleanValueOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,162 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.aconfig.storage;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class PackageTable {
|
||||||
|
|
||||||
|
private Header mHeader;
|
||||||
|
private Map<String, Node> mNodeMap;
|
||||||
|
|
||||||
|
public static PackageTable fromBytes(ByteBuffer bytes) {
|
||||||
|
PackageTable packageTable = new PackageTable();
|
||||||
|
ByteBufferReader reader = new ByteBufferReader(bytes);
|
||||||
|
Header header = Header.fromBytes(reader);
|
||||||
|
packageTable.mHeader = header;
|
||||||
|
packageTable.mNodeMap = new HashMap(TableUtils.getTableSize(header.mNumPackages));
|
||||||
|
reader.position(header.mNodeOffset);
|
||||||
|
for (int i = 0; i < header.mNumPackages; i++) {
|
||||||
|
Node node = Node.fromBytes(reader);
|
||||||
|
packageTable.mNodeMap.put(node.mPackageName, node);
|
||||||
|
}
|
||||||
|
return packageTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Node get(String packageName) {
|
||||||
|
return mNodeMap.get(packageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Header getHeader() {
|
||||||
|
return mHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Header {
|
||||||
|
|
||||||
|
private int mVersion;
|
||||||
|
private String mContainer;
|
||||||
|
private FileType mFileType;
|
||||||
|
private int mFileSize;
|
||||||
|
private int mNumPackages;
|
||||||
|
private int mBucketOffset;
|
||||||
|
private int mNodeOffset;
|
||||||
|
|
||||||
|
public static Header fromBytes(ByteBufferReader reader) {
|
||||||
|
Header header = new Header();
|
||||||
|
header.mVersion = reader.readInt();
|
||||||
|
header.mContainer = reader.readString();
|
||||||
|
header.mFileType = FileType.fromInt(reader.readByte());
|
||||||
|
header.mFileSize = reader.readInt();
|
||||||
|
header.mNumPackages = reader.readInt();
|
||||||
|
header.mBucketOffset = reader.readInt();
|
||||||
|
header.mNodeOffset = reader.readInt();
|
||||||
|
|
||||||
|
if (header.mFileType != FileType.PACKAGE_MAP) {
|
||||||
|
throw new AconfigStorageException("binary file is not a package map");
|
||||||
|
}
|
||||||
|
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVersion() {
|
||||||
|
return mVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContainer() {
|
||||||
|
return mContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileType getFileType() {
|
||||||
|
return mFileType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFileSize() {
|
||||||
|
return mFileSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumPackages() {
|
||||||
|
return mNumPackages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBucketOffset() {
|
||||||
|
return mBucketOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNodeOffset() {
|
||||||
|
return mNodeOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Node {
|
||||||
|
|
||||||
|
private String mPackageName;
|
||||||
|
private int mPackageId;
|
||||||
|
private int mBooleanStartIndex;
|
||||||
|
private int mNextOffset;
|
||||||
|
|
||||||
|
public static Node fromBytes(ByteBufferReader reader) {
|
||||||
|
Node node = new Node();
|
||||||
|
node.mPackageName = reader.readString();
|
||||||
|
node.mPackageId = reader.readInt();
|
||||||
|
node.mBooleanStartIndex = reader.readInt();
|
||||||
|
node.mNextOffset = reader.readInt();
|
||||||
|
node.mNextOffset = node.mNextOffset == 0 ? -1 : node.mNextOffset;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(mPackageName, mPackageId, mBooleanStartIndex, mNextOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj == null || !(obj instanceof Node)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node other = (Node) obj;
|
||||||
|
return Objects.equals(mPackageName, other.mPackageName)
|
||||||
|
&& mPackageId == other.mPackageId
|
||||||
|
&& mBooleanStartIndex == other.mBooleanStartIndex
|
||||||
|
&& mNextOffset == other.mNextOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPackageName() {
|
||||||
|
return mPackageName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPackageId() {
|
||||||
|
return mPackageId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBooleanStartIndex() {
|
||||||
|
return mBooleanStartIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNextOffset() {
|
||||||
|
return mNextOffset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.aconfig.storage;
|
||||||
|
|
||||||
|
public class TableUtils {
|
||||||
|
|
||||||
|
private static final int[] HASH_PRIMES =
|
||||||
|
new int[] {
|
||||||
|
7,
|
||||||
|
17,
|
||||||
|
29,
|
||||||
|
53,
|
||||||
|
97,
|
||||||
|
193,
|
||||||
|
389,
|
||||||
|
769,
|
||||||
|
1543,
|
||||||
|
3079,
|
||||||
|
6151,
|
||||||
|
12289,
|
||||||
|
24593,
|
||||||
|
49157,
|
||||||
|
98317,
|
||||||
|
196613,
|
||||||
|
393241,
|
||||||
|
786433,
|
||||||
|
1572869,
|
||||||
|
3145739,
|
||||||
|
6291469,
|
||||||
|
12582917,
|
||||||
|
25165843,
|
||||||
|
50331653,
|
||||||
|
100663319,
|
||||||
|
201326611,
|
||||||
|
402653189,
|
||||||
|
805306457,
|
||||||
|
1610612741
|
||||||
|
};
|
||||||
|
|
||||||
|
public static int getTableSize(int numEntries) {
|
||||||
|
for (int i : HASH_PRIMES) {
|
||||||
|
if (i < 2 * numEntries) continue;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
throw new AconfigStorageException("Number of items in a hash table exceeds limit");
|
||||||
|
}
|
||||||
|
}
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
cc_test {
|
cc_test {
|
||||||
name: "aconfig_storage_file.test.cpp",
|
name: "aconfig_storage_file.test.cpp",
|
||||||
team: "trendy_team_android_core_experiments",
|
team: "trendy_team_android_core_experiments",
|
||||||
@@ -21,3 +20,27 @@ cc_test {
|
|||||||
"general-tests",
|
"general-tests",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
android_test {
|
||||||
|
name: "aconfig_storage_file.test.java",
|
||||||
|
team: "trendy_team_android_core_experiments",
|
||||||
|
srcs: [
|
||||||
|
"srcs/**/*.java",
|
||||||
|
],
|
||||||
|
static_libs: [
|
||||||
|
"aconfig_storage_file_java",
|
||||||
|
"androidx.test.runner",
|
||||||
|
"junit",
|
||||||
|
],
|
||||||
|
sdk_version: "test_current",
|
||||||
|
test_config: "AndroidStorageJaveTest.xml",
|
||||||
|
data: [
|
||||||
|
"package.map",
|
||||||
|
"flag.map",
|
||||||
|
"flag.val",
|
||||||
|
"flag.info",
|
||||||
|
],
|
||||||
|
test_suites: [
|
||||||
|
"general-tests",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
27
tools/aconfig/aconfig_storage_file/tests/AndroidManifest.xml
Normal file
27
tools/aconfig/aconfig_storage_file/tests/AndroidManifest.xml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2024 The Android Open Source Project
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="android.aconfig.storage.test">
|
||||||
|
<application>
|
||||||
|
<uses-library android:name="android.test.runner" />
|
||||||
|
</application>
|
||||||
|
|
||||||
|
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
android:targetPackage="android.aconfig.storage.test" />
|
||||||
|
|
||||||
|
</manifest>
|
@@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2024 The Android Open Source Project
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
-->
|
||||||
|
<configuration description="Test aconfig storage java tests">
|
||||||
|
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
|
||||||
|
<option name="cleanup-apks" value="true" />
|
||||||
|
<option name="test-file-name" value="aconfig_storage_file.test.java.apk" />
|
||||||
|
</target_preparer>
|
||||||
|
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
|
||||||
|
<option name="cleanup" value="true" />
|
||||||
|
<option name="push" value="package.map->/data/local/tmp/aconfig_storage_file_test_java/testdata/package.map" />
|
||||||
|
<option name="push" value="flag.map->/data/local/tmp/aconfig_storage_file_test_java/testdata/flag.map" />
|
||||||
|
<option name="push" value="flag.val->/data/local/tmp/aconfig_storage_file_test_java/testdata/flag.val" />
|
||||||
|
<option name="push" value="flag.info->/data/local/tmp/aconfig_storage_file_test_java/testdata/flag.info" />
|
||||||
|
</target_preparer>
|
||||||
|
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
|
||||||
|
<option name="package" value="android.aconfig.storage.test" />
|
||||||
|
<option name="runtime-hint" value="1m" />
|
||||||
|
</test>
|
||||||
|
</configuration>
|
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.aconfig.storage.test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import android.aconfig.storage.ByteBufferReader;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.JUnit4;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
@RunWith(JUnit4.class)
|
||||||
|
public class ByteBufferReaderTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReadByte() {
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(1);
|
||||||
|
byte expect = 10;
|
||||||
|
buffer.put(expect).rewind();
|
||||||
|
|
||||||
|
ByteBufferReader reader = new ByteBufferReader(buffer);
|
||||||
|
assertEquals(expect, reader.readByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReadShort() {
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(4);
|
||||||
|
buffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
short expect = Short.MAX_VALUE;
|
||||||
|
buffer.putShort(expect).rewind();
|
||||||
|
|
||||||
|
ByteBufferReader reader = new ByteBufferReader(buffer);
|
||||||
|
assertEquals(expect, reader.readShort());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReadInt() {
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(4);
|
||||||
|
buffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
int expect = 10000;
|
||||||
|
buffer.putInt(expect).rewind();
|
||||||
|
|
||||||
|
ByteBufferReader reader = new ByteBufferReader(buffer);
|
||||||
|
assertEquals(expect, reader.readInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReadString() {
|
||||||
|
String expect = "test read string";
|
||||||
|
byte[] bytes = expect.getBytes(StandardCharsets.UTF_8);
|
||||||
|
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(expect.length() * 2 + 4);
|
||||||
|
buffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
buffer.putInt(expect.length()).put(bytes).rewind();
|
||||||
|
|
||||||
|
ByteBufferReader reader = new ByteBufferReader(buffer);
|
||||||
|
|
||||||
|
assertEquals(expect, reader.readString());
|
||||||
|
}
|
||||||
|
}
|
103
tools/aconfig/aconfig_storage_file/tests/srcs/FlagTableTest.java
Normal file
103
tools/aconfig/aconfig_storage_file/tests/srcs/FlagTableTest.java
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.aconfig.storage.test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import android.aconfig.storage.FileType;
|
||||||
|
import android.aconfig.storage.FlagTable;
|
||||||
|
import android.aconfig.storage.FlagType;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.JUnit4;
|
||||||
|
|
||||||
|
@RunWith(JUnit4.class)
|
||||||
|
public class FlagTableTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFlagTable_rightHeader() throws Exception {
|
||||||
|
FlagTable flagTable = FlagTable.fromBytes(TestDataUtils.getTestFlagMapByteBuffer());
|
||||||
|
FlagTable.Header header = flagTable.getHeader();
|
||||||
|
assertEquals(1, header.getVersion());
|
||||||
|
assertEquals("mockup", header.getContainer());
|
||||||
|
assertEquals(FileType.FLAG_MAP, header.getFileType());
|
||||||
|
assertEquals(321, header.getFileSize());
|
||||||
|
assertEquals(8, header.getNumFlags());
|
||||||
|
assertEquals(31, header.getBucketOffset());
|
||||||
|
assertEquals(99, header.getNodeOffset());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFlagTable_rightNode() throws Exception {
|
||||||
|
FlagTable flagTable = FlagTable.fromBytes(TestDataUtils.getTestFlagMapByteBuffer());
|
||||||
|
|
||||||
|
FlagTable.Node node1 = flagTable.get(0, "enabled_ro");
|
||||||
|
FlagTable.Node node2 = flagTable.get(0, "enabled_rw");
|
||||||
|
FlagTable.Node node3 = flagTable.get(2, "enabled_rw");
|
||||||
|
FlagTable.Node node4 = flagTable.get(1, "disabled_rw");
|
||||||
|
FlagTable.Node node5 = flagTable.get(1, "enabled_fixed_ro");
|
||||||
|
FlagTable.Node node6 = flagTable.get(1, "enabled_ro");
|
||||||
|
FlagTable.Node node7 = flagTable.get(2, "enabled_fixed_ro");
|
||||||
|
FlagTable.Node node8 = flagTable.get(0, "disabled_rw");
|
||||||
|
|
||||||
|
assertEquals("enabled_ro", node1.getFlagName());
|
||||||
|
assertEquals("enabled_rw", node2.getFlagName());
|
||||||
|
assertEquals("enabled_rw", node3.getFlagName());
|
||||||
|
assertEquals("disabled_rw", node4.getFlagName());
|
||||||
|
assertEquals("enabled_fixed_ro", node5.getFlagName());
|
||||||
|
assertEquals("enabled_ro", node6.getFlagName());
|
||||||
|
assertEquals("enabled_fixed_ro", node7.getFlagName());
|
||||||
|
assertEquals("disabled_rw", node8.getFlagName());
|
||||||
|
|
||||||
|
assertEquals(0, node1.getPackageId());
|
||||||
|
assertEquals(0, node2.getPackageId());
|
||||||
|
assertEquals(2, node3.getPackageId());
|
||||||
|
assertEquals(1, node4.getPackageId());
|
||||||
|
assertEquals(1, node5.getPackageId());
|
||||||
|
assertEquals(1, node6.getPackageId());
|
||||||
|
assertEquals(2, node7.getPackageId());
|
||||||
|
assertEquals(0, node8.getPackageId());
|
||||||
|
|
||||||
|
assertEquals(FlagType.ReadOnlyBoolean, node1.getFlagType());
|
||||||
|
assertEquals(FlagType.ReadWriteBoolean, node2.getFlagType());
|
||||||
|
assertEquals(FlagType.ReadWriteBoolean, node3.getFlagType());
|
||||||
|
assertEquals(FlagType.ReadWriteBoolean, node4.getFlagType());
|
||||||
|
assertEquals(FlagType.FixedReadOnlyBoolean, node5.getFlagType());
|
||||||
|
assertEquals(FlagType.ReadOnlyBoolean, node6.getFlagType());
|
||||||
|
assertEquals(FlagType.FixedReadOnlyBoolean, node7.getFlagType());
|
||||||
|
assertEquals(FlagType.ReadWriteBoolean, node8.getFlagType());
|
||||||
|
|
||||||
|
assertEquals(1, node1.getFlagIndex());
|
||||||
|
assertEquals(2, node2.getFlagIndex());
|
||||||
|
assertEquals(1, node3.getFlagIndex());
|
||||||
|
assertEquals(0, node4.getFlagIndex());
|
||||||
|
assertEquals(1, node5.getFlagIndex());
|
||||||
|
assertEquals(2, node6.getFlagIndex());
|
||||||
|
assertEquals(0, node7.getFlagIndex());
|
||||||
|
assertEquals(0, node8.getFlagIndex());
|
||||||
|
|
||||||
|
assertEquals(-1, node1.getNextOffset());
|
||||||
|
assertEquals(151, node2.getNextOffset());
|
||||||
|
assertEquals(-1, node3.getNextOffset());
|
||||||
|
assertEquals(-1, node4.getNextOffset());
|
||||||
|
assertEquals(236, node5.getNextOffset());
|
||||||
|
assertEquals(-1, node6.getNextOffset());
|
||||||
|
assertEquals(-1, node7.getNextOffset());
|
||||||
|
assertEquals(-1, node8.getNextOffset());
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.aconfig.storage.test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import android.aconfig.storage.FileType;
|
||||||
|
import android.aconfig.storage.FlagTable;
|
||||||
|
import android.aconfig.storage.FlagValueList;
|
||||||
|
import android.aconfig.storage.PackageTable;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.JUnit4;
|
||||||
|
|
||||||
|
@RunWith(JUnit4.class)
|
||||||
|
public class FlagValueListTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFlagValueList_rightHeader() throws Exception {
|
||||||
|
FlagValueList flagValueList =
|
||||||
|
FlagValueList.fromBytes(TestDataUtils.getTestFlagValByteBuffer());
|
||||||
|
FlagValueList.Header header = flagValueList.getHeader();
|
||||||
|
assertEquals(1, header.getVersion());
|
||||||
|
assertEquals("mockup", header.getContainer());
|
||||||
|
assertEquals(FileType.FLAG_VAL, header.getFileType());
|
||||||
|
assertEquals(35, header.getFileSize());
|
||||||
|
assertEquals(8, header.getNumFlags());
|
||||||
|
assertEquals(27, header.getBooleanValueOffset());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFlagValueList_rightNode() throws Exception {
|
||||||
|
FlagValueList flagValueList =
|
||||||
|
FlagValueList.fromBytes(TestDataUtils.getTestFlagValByteBuffer());
|
||||||
|
|
||||||
|
boolean[] expected = new boolean[] {false, true, true, false, true, true, true, true};
|
||||||
|
assertEquals(expected.length, flagValueList.size());
|
||||||
|
|
||||||
|
for (int i = 0; i < flagValueList.size(); i++) {
|
||||||
|
assertEquals(expected[i], flagValueList.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFlagValueList_getValue() throws Exception {
|
||||||
|
PackageTable packageTable =
|
||||||
|
PackageTable.fromBytes(TestDataUtils.getTestPackageMapByteBuffer());
|
||||||
|
FlagTable flagTable = FlagTable.fromBytes(TestDataUtils.getTestFlagMapByteBuffer());
|
||||||
|
|
||||||
|
FlagValueList flagValueList =
|
||||||
|
FlagValueList.fromBytes(TestDataUtils.getTestFlagValByteBuffer());
|
||||||
|
|
||||||
|
PackageTable.Node pNode = packageTable.get("com.android.aconfig.storage.test_1");
|
||||||
|
FlagTable.Node fNode = flagTable.get(pNode.getPackageId(), "enabled_rw");
|
||||||
|
assertTrue(flagValueList.get(pNode.getBooleanStartIndex() + fNode.getFlagIndex()));
|
||||||
|
|
||||||
|
pNode = packageTable.get("com.android.aconfig.storage.test_4");
|
||||||
|
fNode = flagTable.get(pNode.getPackageId(), "enabled_fixed_ro");
|
||||||
|
assertTrue(flagValueList.get(pNode.getBooleanStartIndex() + fNode.getFlagIndex()));
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.aconfig.storage.test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import android.aconfig.storage.FileType;
|
||||||
|
import android.aconfig.storage.PackageTable;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.JUnit4;
|
||||||
|
|
||||||
|
@RunWith(JUnit4.class)
|
||||||
|
public class PackageTableTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPackageTable_rightHeader() throws Exception {
|
||||||
|
PackageTable packageTable =
|
||||||
|
PackageTable.fromBytes(TestDataUtils.getTestPackageMapByteBuffer());
|
||||||
|
PackageTable.Header header = packageTable.getHeader();
|
||||||
|
assertEquals(1, header.getVersion());
|
||||||
|
assertEquals("mockup", header.getContainer());
|
||||||
|
assertEquals(FileType.PACKAGE_MAP, header.getFileType());
|
||||||
|
assertEquals(209, header.getFileSize());
|
||||||
|
assertEquals(3, header.getNumPackages());
|
||||||
|
assertEquals(31, header.getBucketOffset());
|
||||||
|
assertEquals(59, header.getNodeOffset());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPackageTable_rightNode() throws Exception {
|
||||||
|
PackageTable packageTable =
|
||||||
|
PackageTable.fromBytes(TestDataUtils.getTestPackageMapByteBuffer());
|
||||||
|
|
||||||
|
PackageTable.Node node1 = packageTable.get("com.android.aconfig.storage.test_1");
|
||||||
|
PackageTable.Node node2 = packageTable.get("com.android.aconfig.storage.test_2");
|
||||||
|
PackageTable.Node node4 = packageTable.get("com.android.aconfig.storage.test_4");
|
||||||
|
|
||||||
|
assertEquals("com.android.aconfig.storage.test_1", node1.getPackageName());
|
||||||
|
assertEquals("com.android.aconfig.storage.test_2", node2.getPackageName());
|
||||||
|
assertEquals("com.android.aconfig.storage.test_4", node4.getPackageName());
|
||||||
|
|
||||||
|
assertEquals(0, node1.getPackageId());
|
||||||
|
assertEquals(1, node2.getPackageId());
|
||||||
|
assertEquals(2, node4.getPackageId());
|
||||||
|
|
||||||
|
assertEquals(0, node1.getBooleanStartIndex());
|
||||||
|
assertEquals(3, node2.getBooleanStartIndex());
|
||||||
|
assertEquals(6, node4.getBooleanStartIndex());
|
||||||
|
|
||||||
|
assertEquals(159, node1.getNextOffset());
|
||||||
|
assertEquals(-1, node2.getNextOffset());
|
||||||
|
assertEquals(-1, node4.getNextOffset());
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.aconfig.storage.test;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public final class TestDataUtils {
|
||||||
|
private static final String TEST_PACKAGE_MAP_PATH = "package.map";
|
||||||
|
private static final String TEST_FLAG_MAP_PATH = "flag.map";
|
||||||
|
private static final String TEST_FLAG_VAL_PATH = "flag.val";
|
||||||
|
private static final String TEST_FLAG_INFO_PATH = "flag.info";
|
||||||
|
|
||||||
|
private static final String TESTDATA_PATH =
|
||||||
|
"/data/local/tmp/aconfig_storage_file_test_java/testdata/";
|
||||||
|
|
||||||
|
public static ByteBuffer getTestPackageMapByteBuffer() throws Exception {
|
||||||
|
return readFile(TESTDATA_PATH + TEST_PACKAGE_MAP_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ByteBuffer getTestFlagMapByteBuffer() throws Exception {
|
||||||
|
return readFile(TESTDATA_PATH + TEST_FLAG_MAP_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ByteBuffer getTestFlagValByteBuffer() throws Exception {
|
||||||
|
return readFile(TESTDATA_PATH + TEST_FLAG_VAL_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ByteBuffer getTestFlagInfoByteBuffer() throws Exception {
|
||||||
|
return readFile(TESTDATA_PATH + TEST_FLAG_INFO_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ByteBuffer readFile(String fileName) throws Exception {
|
||||||
|
InputStream input = new FileInputStream(fileName);
|
||||||
|
return ByteBuffer.wrap(input.readAllBytes());
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user