Add semantic version model and test

This commit is contained in:
Manfred Karrer 2017-05-13 14:01:05 +02:00
parent 8eaa7b5cd6
commit 603c3c512e
4 changed files with 130 additions and 130 deletions

View file

@ -20,13 +20,44 @@ package io.bisq.common.app;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static com.google.common.base.Preconditions.checkArgument;
public class Version {
private static final Logger log = LoggerFactory.getLogger(Version.class);
// 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
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.
// If objects are used for both network and database the network version is applied.

View 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"));
}
}

View file

@ -17,10 +17,9 @@
package io.bisq.core.alert;
import com.google.common.annotations.VisibleForTesting;
import com.google.protobuf.ByteString;
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.network.p2p.storage.payload.StoragePayload;
import lombok.EqualsAndHashCode;
@ -49,103 +48,56 @@ public final class Alert implements StoragePayload {
@Nullable
private String signatureAsBase64;
@Nullable
private PublicKey storagePublicKey;
private byte[] ownerPubKeyBytes;
@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
// 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.
@Nullable
private Map<String, String> extraDataMap;
// StoragePayload
private transient PublicKey ownerPubKey;
public Alert(String message,
boolean isUpdateInfo,
String version) {
this.message = message;
this.isUpdateInfo = isUpdateInfo;
this.version = version;
}
///////////////////////////////////////////////////////////////////////////////////////////
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
public Alert(String message,
boolean isUpdateInfo,
String version,
@Nullable byte[] storagePublicKeyBytes,
@Nullable String signatureAsBase64,
@Nullable Map<String, String> extraDataMap) {
byte[] ownerPubKeyBytes,
String signatureAsBase64,
Map<String, String> extraDataMap) {
this.message = message;
this.isUpdateInfo = isUpdateInfo;
this.version = version;
this.storagePublicKeyBytes = storagePublicKeyBytes;
this.ownerPubKeyBytes = ownerPubKeyBytes;
this.signatureAsBase64 = signatureAsBase64;
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
public PB.StoragePayload toProtoMessage() {
checkNotNull(getStoragePublicKeyBytes(), "storagePublicKeyBytes must not be null");
checkNotNull(getSignatureAsBase64(), "signatureAsBase64 must not be null");
checkNotNull(ownerPubKeyBytes, "storagePublicKeyBytes must not be null");
checkNotNull(signatureAsBase64, "signatureAsBase64 must not be null");
final PB.Alert.Builder builder = PB.Alert.newBuilder()
.setMessage(getMessage())
.setVersion(getVersion())
.setIsUpdateInfo(isUpdateInfo())
.setSignatureAsBase64(getSignatureAsBase64())
.setStoragePublicKeyBytes(ByteString.copyFrom(getStoragePublicKeyBytes()));
Optional.ofNullable(getExtraDataMap()).ifPresent(builder::putAllExtraDataMap);
.setVersion(getVersion())
.setOwnerPubKeyBytes(ByteString.copyFrom(ownerPubKeyBytes))
.setSignatureAsBase64(getSignatureAsBase64());
Optional.ofNullable(getExtraDataMap()).ifPresent(builder::putAllExtraData);
return PB.StoragePayload.newBuilder().setAlert(builder).build();
}
@ -153,9 +105,29 @@ public final class Alert implements StoragePayload {
return new Alert(alert.getMessage(),
alert.getIsUpdateInfo(),
alert.getVersion(),
alert.getStoragePublicKeyBytes().toByteArray(),
alert.getOwnerPubKeyBytes().toByteArray(),
alert.getSignatureAsBase64(),
CollectionUtils.isEmpty(alert.getExtraDataMapMap()) ?
null : alert.getExtraDataMapMap());
CollectionUtils.isEmpty(alert.getExtraDataMap()) ?
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);
}
}

View file

@ -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"));
}
}