Files
ERP/oa-backend/src/test/java/com/kaidi/oa/service/SystemUpdateServiceTest.java
T

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