mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 23:18:17 +01:00
Add semantic version model and test
This commit is contained in:
parent
8eaa7b5cd6
commit
603c3c512e
4 changed files with 130 additions and 130 deletions
|
@ -20,13 +20,44 @@ package io.bisq.common.app;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
|
||||||
public class Version {
|
public class Version {
|
||||||
private static final Logger log = LoggerFactory.getLogger(Version.class);
|
private static final Logger log = LoggerFactory.getLogger(Version.class);
|
||||||
|
|
||||||
// The application versions
|
// The application versions
|
||||||
// VERSION = 0.5.0.0 introduces proto buffer for the P2P network and local DB and is a not backward compatible update
|
// VERSION = 0.5.0 introduces proto buffer for the P2P network and local DB and is a not backward compatible update
|
||||||
// Therefore all sub versions start again with 1
|
// Therefore all sub versions start again with 1
|
||||||
public static final String VERSION = "0.5.0.0";
|
// We use semantic versioning with major, minor and patch
|
||||||
|
public static final String VERSION = "0.5.0";
|
||||||
|
|
||||||
|
public static int getMajorVersion(String version) {
|
||||||
|
return getSubVersion(version, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getMinorVersion(String version) {
|
||||||
|
return getSubVersion(version, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getPatchVersion(String version) {
|
||||||
|
return getSubVersion(version, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isNewVersion(String newVersion) {
|
||||||
|
return isNewVersion(newVersion, VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isNewVersion(String newVersion, String currentVersion) {
|
||||||
|
return getMajorVersion(newVersion) > getMajorVersion(currentVersion) ||
|
||||||
|
getMinorVersion(newVersion) > getMinorVersion(currentVersion) ||
|
||||||
|
getPatchVersion(newVersion) > getPatchVersion(currentVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getSubVersion(String version, int index) {
|
||||||
|
final String[] split = version.split("\\.");
|
||||||
|
checkArgument(split.length == 3, "Version number must be in semantic version format (contain 2 '.'). version=" + version);
|
||||||
|
return Integer.parseInt(split[index]);
|
||||||
|
}
|
||||||
|
|
||||||
// The version no. for the objects sent over the network. A change will break the serialization of old objects.
|
// The version no. for the objects sent over the network. A change will break the serialization of old objects.
|
||||||
// If objects are used for both network and database the network version is applied.
|
// If objects are used for both network and database the network version is applied.
|
||||||
|
|
47
common/src/test/java/io/bisq/common/app/VersionTest.java
Normal file
47
common/src/test/java/io/bisq/common/app/VersionTest.java
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* This file is part of bisq.
|
||||||
|
*
|
||||||
|
* bisq is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* bisq is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||||
|
* License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.bisq.common.app;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class VersionTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVersionNumber() {
|
||||||
|
assertEquals(0, Version.getMajorVersion("0.0.0"));
|
||||||
|
assertEquals(1, Version.getMajorVersion("1.0.0"));
|
||||||
|
|
||||||
|
assertEquals(0, Version.getMinorVersion("0.0.0"));
|
||||||
|
assertEquals(5, Version.getMinorVersion("0.5.0"));
|
||||||
|
|
||||||
|
assertEquals(0, Version.getPatchVersion("0.0.0"));
|
||||||
|
assertEquals(5, Version.getPatchVersion("0.0.5"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIsNewVersion() {
|
||||||
|
assertFalse(Version.isNewVersion("0.0.0", "0.0.0"));
|
||||||
|
assertTrue(Version.isNewVersion("1.0.0", "0.0.0"));
|
||||||
|
assertTrue(Version.isNewVersion("0.1.0", "0.0.0"));
|
||||||
|
assertTrue(Version.isNewVersion("0.0.1", "0.0.0"));
|
||||||
|
assertTrue(Version.isNewVersion("0.5.1", "0.5.0"));
|
||||||
|
assertFalse(Version.isNewVersion("0.5.0", "0.5.1"));
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,10 +17,9 @@
|
||||||
|
|
||||||
package io.bisq.core.alert;
|
package io.bisq.core.alert;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import io.bisq.common.app.Version;
|
import io.bisq.common.app.Version;
|
||||||
import io.bisq.common.crypto.CryptoUtils;
|
import io.bisq.common.crypto.Sig;
|
||||||
import io.bisq.generated.protobuffer.PB;
|
import io.bisq.generated.protobuffer.PB;
|
||||||
import io.bisq.network.p2p.storage.payload.StoragePayload;
|
import io.bisq.network.p2p.storage.payload.StoragePayload;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
@ -49,103 +48,56 @@ public final class Alert implements StoragePayload {
|
||||||
@Nullable
|
@Nullable
|
||||||
private String signatureAsBase64;
|
private String signatureAsBase64;
|
||||||
@Nullable
|
@Nullable
|
||||||
private PublicKey storagePublicKey;
|
private byte[] ownerPubKeyBytes;
|
||||||
@Nullable
|
@Nullable
|
||||||
private final byte[] storagePublicKeyBytes;
|
private PublicKey ownerPubKey;
|
||||||
|
|
||||||
// Should be only used in emergency case if we need to add data but do not want to break backward compatibility
|
// Should be only used in emergency case if we need to add data but do not want to break backward compatibility
|
||||||
// at the P2P network storage checks. The hash of the object will be used to verify if the data is valid. Any new
|
// at the P2P network storage checks. The hash of the object will be used to verify if the data is valid. Any new
|
||||||
// field in a class would break that hash and therefore break the storage mechanism.
|
// field in a class would break that hash and therefore break the storage mechanism.
|
||||||
@Nullable
|
@Nullable
|
||||||
private Map<String, String> extraDataMap;
|
private Map<String, String> extraDataMap;
|
||||||
|
|
||||||
// StoragePayload
|
public Alert(String message,
|
||||||
private transient PublicKey ownerPubKey;
|
boolean isUpdateInfo,
|
||||||
|
String version) {
|
||||||
|
this.message = message;
|
||||||
|
this.isUpdateInfo = isUpdateInfo;
|
||||||
|
this.version = version;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// PROTO BUFFER
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
public Alert(String message,
|
public Alert(String message,
|
||||||
boolean isUpdateInfo,
|
boolean isUpdateInfo,
|
||||||
String version,
|
String version,
|
||||||
@Nullable byte[] storagePublicKeyBytes,
|
byte[] ownerPubKeyBytes,
|
||||||
@Nullable String signatureAsBase64,
|
String signatureAsBase64,
|
||||||
@Nullable Map<String, String> extraDataMap) {
|
Map<String, String> extraDataMap) {
|
||||||
this.message = message;
|
this.message = message;
|
||||||
this.isUpdateInfo = isUpdateInfo;
|
this.isUpdateInfo = isUpdateInfo;
|
||||||
this.version = version;
|
this.version = version;
|
||||||
this.storagePublicKeyBytes = storagePublicKeyBytes;
|
this.ownerPubKeyBytes = ownerPubKeyBytes;
|
||||||
this.signatureAsBase64 = signatureAsBase64;
|
this.signatureAsBase64 = signatureAsBase64;
|
||||||
this.extraDataMap = extraDataMap;
|
this.extraDataMap = extraDataMap;
|
||||||
|
|
||||||
|
ownerPubKey = Sig.getSigPublicKeyFromBytes(ownerPubKeyBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Alert(String message,
|
|
||||||
boolean isUpdateInfo,
|
|
||||||
String version) {
|
|
||||||
this(message, isUpdateInfo, version, null, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setSigAndPubKey(String signatureAsBase64, PublicKey storagePublicKey) {
|
|
||||||
this.signatureAsBase64 = signatureAsBase64;
|
|
||||||
this.storagePublicKey = storagePublicKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isNewVersion() {
|
|
||||||
return isNewVersion(Version.VERSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
protected boolean isNewVersion(String myVersion) {
|
|
||||||
// We need to support different version usages (0.5, 0.5.1, 0.5.1.1.1, 0.5.10.1)
|
|
||||||
// So we fill up the right part up to 8 digits 0.5 -> 05000000, 0.5.1.1.1 -> 05111000
|
|
||||||
// that should handle all cases.
|
|
||||||
// TODO make it more elegant and add tests :-)
|
|
||||||
|
|
||||||
// In case the input comes in a corrupted format we don't want to screw up teh app
|
|
||||||
try {
|
|
||||||
String myVersionString = myVersion.replace(".", "");
|
|
||||||
while (myVersionString.length() < 9)
|
|
||||||
myVersionString += "0";
|
|
||||||
int myVersionNum = Integer.valueOf(myVersionString);
|
|
||||||
String alertVersionString = getVersion().replace(".", "");
|
|
||||||
while (alertVersionString.length() < 9)
|
|
||||||
alertVersionString += "0";
|
|
||||||
int alertVersionNum = Integer.valueOf(alertVersionString);
|
|
||||||
return myVersionNum < alertVersionNum;
|
|
||||||
} catch (Throwable t) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//StoragePayload
|
|
||||||
@Override
|
|
||||||
public long getTTL() {
|
|
||||||
return TimeUnit.DAYS.toMillis(30);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PublicKey getOwnerPubKey() {
|
|
||||||
try {
|
|
||||||
checkNotNull(getStoragePublicKeyBytes(), "alertVO.getStoragePublicKeyBytes() must not be null");
|
|
||||||
if (ownerPubKey == null)
|
|
||||||
ownerPubKey = CryptoUtils.getPubKeyFromBytes(getStoragePublicKeyBytes());
|
|
||||||
return ownerPubKey;
|
|
||||||
} catch (Throwable t) {
|
|
||||||
log.error(t.toString());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Marshaller
|
|
||||||
@Override
|
@Override
|
||||||
public PB.StoragePayload toProtoMessage() {
|
public PB.StoragePayload toProtoMessage() {
|
||||||
checkNotNull(getStoragePublicKeyBytes(), "storagePublicKeyBytes must not be null");
|
checkNotNull(ownerPubKeyBytes, "storagePublicKeyBytes must not be null");
|
||||||
checkNotNull(getSignatureAsBase64(), "signatureAsBase64 must not be null");
|
checkNotNull(signatureAsBase64, "signatureAsBase64 must not be null");
|
||||||
final PB.Alert.Builder builder = PB.Alert.newBuilder()
|
final PB.Alert.Builder builder = PB.Alert.newBuilder()
|
||||||
.setMessage(getMessage())
|
.setMessage(getMessage())
|
||||||
.setVersion(getVersion())
|
|
||||||
.setIsUpdateInfo(isUpdateInfo())
|
.setIsUpdateInfo(isUpdateInfo())
|
||||||
.setSignatureAsBase64(getSignatureAsBase64())
|
.setVersion(getVersion())
|
||||||
.setStoragePublicKeyBytes(ByteString.copyFrom(getStoragePublicKeyBytes()));
|
.setOwnerPubKeyBytes(ByteString.copyFrom(ownerPubKeyBytes))
|
||||||
Optional.ofNullable(getExtraDataMap()).ifPresent(builder::putAllExtraDataMap);
|
.setSignatureAsBase64(getSignatureAsBase64());
|
||||||
|
Optional.ofNullable(getExtraDataMap()).ifPresent(builder::putAllExtraData);
|
||||||
return PB.StoragePayload.newBuilder().setAlert(builder).build();
|
return PB.StoragePayload.newBuilder().setAlert(builder).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,9 +105,29 @@ public final class Alert implements StoragePayload {
|
||||||
return new Alert(alert.getMessage(),
|
return new Alert(alert.getMessage(),
|
||||||
alert.getIsUpdateInfo(),
|
alert.getIsUpdateInfo(),
|
||||||
alert.getVersion(),
|
alert.getVersion(),
|
||||||
alert.getStoragePublicKeyBytes().toByteArray(),
|
alert.getOwnerPubKeyBytes().toByteArray(),
|
||||||
alert.getSignatureAsBase64(),
|
alert.getSignatureAsBase64(),
|
||||||
CollectionUtils.isEmpty(alert.getExtraDataMapMap()) ?
|
CollectionUtils.isEmpty(alert.getExtraDataMap()) ?
|
||||||
null : alert.getExtraDataMapMap());
|
null : alert.getExtraDataMap());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// API
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public void setSigAndPubKey(String signatureAsBase64, PublicKey ownerPubKey) {
|
||||||
|
this.signatureAsBase64 = signatureAsBase64;
|
||||||
|
this.ownerPubKey = ownerPubKey;
|
||||||
|
ownerPubKeyBytes = Sig.getSigPublicKeyBytes(ownerPubKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNewVersion() {
|
||||||
|
return Version.isNewVersion(version);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getTTL() {
|
||||||
|
return TimeUnit.DAYS.toMillis(30);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of bisq.
|
|
||||||
*
|
|
||||||
* bisq is free software: you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or (at
|
|
||||||
* your option) any later version.
|
|
||||||
*
|
|
||||||
* bisq is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
|
||||||
* License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with bisq. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.bisq.core.alert;
|
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
public class AlertTest {
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(AlertTest.class);
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIsNewVersion() {
|
|
||||||
Alert alert = new Alert(null, true, "0.4.9.9.1");
|
|
||||||
assertTrue(alert.isNewVersion("0.4.9.9"));
|
|
||||||
assertTrue(alert.isNewVersion("0.4.9.8"));
|
|
||||||
assertTrue(alert.isNewVersion("0.4.9"));
|
|
||||||
assertTrue(alert.isNewVersion("0.4.9.9.0"));
|
|
||||||
assertFalse(alert.isNewVersion("0.4.9.9.1"));
|
|
||||||
|
|
||||||
alert = new Alert(null, true, "0.4.9.9.2");
|
|
||||||
assertTrue(alert.isNewVersion("0.4.9.9.1"));
|
|
||||||
assertFalse(alert.isNewVersion("0.4.9.9.2"));
|
|
||||||
assertTrue(alert.isNewVersion("0.4.9.8"));
|
|
||||||
assertTrue(alert.isNewVersion("0.4.9"));
|
|
||||||
|
|
||||||
alert = new Alert(null, true, "0.4.9.9");
|
|
||||||
assertTrue(alert.isNewVersion("0.4.9"));
|
|
||||||
assertTrue(alert.isNewVersion("0.4.9.8"));
|
|
||||||
assertFalse(alert.isNewVersion("0.4.9.9"));
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue