133 lines
6.0 KiB
Java
133 lines
6.0 KiB
Java
package com.kaidi.oa.service;
|
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
import com.kaidi.oa.common.ApiException;
|
|
import com.kaidi.oa.config.UpdateProperties;
|
|
import com.sun.net.httpserver.HttpServer;
|
|
import org.junit.jupiter.api.Test;
|
|
import org.springframework.beans.factory.ObjectProvider;
|
|
import org.springframework.boot.info.BuildProperties;
|
|
|
|
import java.net.InetSocketAddress;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.time.Instant;
|
|
import java.util.Properties;
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
|
import static org.mockito.Mockito.mock;
|
|
import static org.mockito.Mockito.when;
|
|
|
|
class SystemUpdateServiceTest {
|
|
|
|
@Test
|
|
void comparesReleaseVersionsWithoutLexicographicMistakes() {
|
|
assertThat(SystemUpdateService.compareVersions("v0.10.0", "0.9.9")).isPositive();
|
|
assertThat(SystemUpdateService.compareVersions("1.0.0", "1.0.0-rc.1")).isPositive();
|
|
assertThat(SystemUpdateService.compareVersions("1.2", "1.2.0")).isZero();
|
|
assertThat(SystemUpdateService.compareVersions("1.0.0+build.2", "1.0.0+build.1")).isZero();
|
|
assertThat(SystemUpdateService.compareVersions("1.0.0-alpha.10", "1.0.0-alpha.2")).isPositive();
|
|
assertThat(SystemUpdateService.compareVersions("1.0.0-alpha.1", "1.0.0-alpha.beta")).isNegative();
|
|
assertThat(SystemUpdateService.compareVersions("999999999999999999999.0.0", "2.0.0")).isPositive();
|
|
assertThat(SystemUpdateService.compareVersions("1.0.0", "dev")).isPositive();
|
|
}
|
|
|
|
@Test
|
|
void checksLatestGiteaReleaseAndRequiresSignedAssetSet() throws Exception {
|
|
HttpServer server = HttpServer.create(new InetSocketAddress("127.0.0.1", 0), 0);
|
|
server.createContext("/api/v1/repos/awaioi/ERP/releases/latest", exchange -> {
|
|
byte[] body = """
|
|
{
|
|
"tag_name": "v0.2.0",
|
|
"body": "PostgreSQL production release",
|
|
"draft": false,
|
|
"prerelease": false,
|
|
"published_at": "2026-08-03T10:00:00Z",
|
|
"assets": [
|
|
{"name":"kaidi-erp-0.2.0.tar.gz","browser_download_url":"https://example.test/app","size":123},
|
|
{"name":"SHA256SUMS","browser_download_url":"https://example.test/sums","size":64},
|
|
{"name":"SHA256SUMS.sig","browser_download_url":"https://example.test/sig","size":64}
|
|
]
|
|
}
|
|
""".getBytes(StandardCharsets.UTF_8);
|
|
exchange.getResponseHeaders().add("Content-Type", "application/json");
|
|
exchange.sendResponseHeaders(200, body.length);
|
|
exchange.getResponseBody().write(body);
|
|
exchange.close();
|
|
});
|
|
server.start();
|
|
try {
|
|
UpdateProperties properties = configuredProperties(server.getAddress().getPort());
|
|
SystemUpdateService service = service(properties, "0.1.0");
|
|
|
|
SystemUpdateService.UpdateStatus status = service.check();
|
|
|
|
assertThat(status.updateAvailable()).isTrue();
|
|
assertThat(status.currentVersion()).isEqualTo("0.1.0");
|
|
assertThat(status.latestVersion()).isEqualTo("0.2.0");
|
|
assertThat(status.assets()).extracting(SystemUpdateService.ReleaseAsset::name)
|
|
.containsExactly("kaidi-erp-0.2.0.tar.gz", "SHA256SUMS", "SHA256SUMS.sig");
|
|
} finally {
|
|
server.stop(0);
|
|
}
|
|
}
|
|
|
|
@Test
|
|
void rejectsPlainHttpUnlessDevelopmentOverrideIsExplicit() {
|
|
UpdateProperties properties = configuredProperties(1);
|
|
properties.setAllowInsecureHttp(false);
|
|
SystemUpdateService service = service(properties, "0.1.0");
|
|
|
|
assertThatThrownBy(service::check)
|
|
.isInstanceOf(ApiException.class)
|
|
.hasMessageContaining("HTTPS");
|
|
}
|
|
|
|
@Test
|
|
void persistedHelperStateComputesAvailabilityFromVersionAndKeepsTimestamp() throws Exception {
|
|
Path stateFile = Files.createTempFile("system-update-state-", ".json");
|
|
try {
|
|
UpdateProperties properties = configuredProperties(1);
|
|
properties.setStateFile(stateFile.toString());
|
|
SystemUpdateService service = service(properties, "0.2.0");
|
|
|
|
Files.writeString(stateFile, """
|
|
{"phase":"FAILED","progress":0,"message":"update failed",\
|
|
"version":"0.2.0","updatedAt":"2026-08-03T12:34:56Z"}
|
|
""");
|
|
SystemUpdateService.UpdateStatus failed = service.status();
|
|
|
|
assertThat(failed.updateAvailable()).isFalse();
|
|
assertThat(failed.checkedAt()).isEqualTo(Instant.parse("2026-08-03T12:34:56Z"));
|
|
|
|
Files.writeString(stateFile, """
|
|
{"phase":"ROLLED_BACK","progress":100,"message":"rolled back",\
|
|
"version":"0.3.0","updatedAt":"2026-08-03T12:35:56Z"}
|
|
""");
|
|
assertThat(service.status().updateAvailable()).isTrue();
|
|
} finally {
|
|
Files.deleteIfExists(stateFile);
|
|
}
|
|
}
|
|
|
|
private static UpdateProperties configuredProperties(int port) {
|
|
UpdateProperties properties = new UpdateProperties();
|
|
properties.setEnabled(true);
|
|
properties.setAllowInsecureHttp(true);
|
|
properties.setGiteaBaseUrl("http://127.0.0.1:" + port);
|
|
properties.setRepository("awaioi/ERP");
|
|
return properties;
|
|
}
|
|
|
|
@SuppressWarnings("unchecked")
|
|
private static SystemUpdateService service(UpdateProperties properties, String version) {
|
|
Properties buildValues = new Properties();
|
|
buildValues.setProperty("version", version);
|
|
ObjectProvider<BuildProperties> provider = mock(ObjectProvider.class);
|
|
when(provider.getIfAvailable()).thenReturn(new BuildProperties(buildValues));
|
|
return new SystemUpdateService(properties, new ObjectMapper(), provider);
|
|
}
|
|
}
|