temporary commit

This commit is contained in:
2025-01-08 23:17:43 +08:00
parent 688a196a52
commit 0fdb37fb54
74 changed files with 3302 additions and 675 deletions

View File

@@ -1,7 +0,0 @@
module net.woggioni.gbcs.test {
requires org.junit.jupiter.api;
requires net.woggioni.gbcs;
requires kotlin.stdlib;
requires java.xml;
requires java.naming;
}

View File

@@ -9,16 +9,13 @@ import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.GeneralNames;
import org.bouncycastle.asn1.x509.KeyPurposeId;
import org.bouncycastle.asn1.x509.KeyUsage;
import org.bouncycastle.asn1.x509.SubjectAltPublicKeyInfo;
import org.bouncycastle.cert.X509v3CertificateBuilder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import java.io.FileOutputStream;
import java.math.BigInteger;
import java.net.InetAddress;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;

View File

@@ -1,7 +1,7 @@
package net.woggioni.gbcs.test
import net.woggioni.gbcs.GradleBuildCacheServer
import net.woggioni.gbcs.configuration.Configuration
import net.woggioni.gbcs.api.Configuration
import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.ClassOrderer
@@ -14,7 +14,7 @@ import java.nio.file.Path
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation::class)
abstract class AbstractServerTest {
abstract class AbstractServerTestKt {
protected lateinit var cfg : Configuration

View File

@@ -1,12 +1,11 @@
package net.woggioni.gbcs.test
import io.netty.handler.codec.Headers
import io.netty.handler.codec.http.HttpResponseStatus
import net.woggioni.gbcs.AbstractNettyHttpAuthenticator.Companion.hashPassword
import net.woggioni.gbcs.Authorizer
import net.woggioni.gbcs.Role
import net.woggioni.gbcs.Xml
import net.woggioni.gbcs.configuration.Configuration
import net.woggioni.gbcs.api.Role
import net.woggioni.gbcs.base.Xml
import net.woggioni.gbcs.api.Configuration
import net.woggioni.gbcs.cache.FileSystemCacheConfiguration
import net.woggioni.gbcs.configuration.Serializer
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Order
@@ -20,10 +19,11 @@ import java.nio.charset.StandardCharsets
import java.nio.file.Path
import java.time.Duration
import java.util.Base64
import java.util.zip.Deflater
import kotlin.random.Random
class BasicAuthServerTest : AbstractServerTest() {
class BasicAuthServerTestKt : AbstractServerTestKt() {
companion object {
private const val PASSWORD = "password"
@@ -33,25 +33,31 @@ class BasicAuthServerTest : AbstractServerTest() {
private val random = Random(101325)
private val keyValuePair = newEntry(random)
private val serverPath = "gbcs"
override fun setUp() {
this.cacheDir = testDir.resolve("cache")
val readersGroup = Configuration.Group("readers", setOf(Role.Reader))
val writersGroup = Configuration.Group("writers", setOf(Role.Writer))
cfg = Configuration.of(
cache = Configuration.FileSystemCache(this.cacheDir, maxAge = Duration.ofSeconds(3600 * 24)),
host = "127.0.0.1",
port = ServerSocket(0).localPort + 1,
users = listOf(
cfg = Configuration(
"127.0.0.1",
ServerSocket(0).localPort + 1,
serverPath,
listOf(
Configuration.User("user1", hashPassword(PASSWORD), setOf(readersGroup)),
Configuration.User("user2", hashPassword(PASSWORD), setOf(writersGroup)),
Configuration.User("user3", hashPassword(PASSWORD), setOf(readersGroup, writersGroup))
).asSequence().map { it.name to it}.toMap(),
groups = sequenceOf(writersGroup, readersGroup).map { it.name to it}.toMap(),
authentication = Configuration.BasicAuthentication(),
useVirtualThread = true,
tls = null,
serverPath = "/"
sequenceOf(writersGroup, readersGroup).map { it.name to it}.toMap(),
FileSystemCacheConfiguration(this.cacheDir,
maxAge = Duration.ofSeconds(3600 * 24),
digestAlgorithm = "MD5",
compressionLevel = Deflater.DEFAULT_COMPRESSION,
compressionEnabled = false
),
Configuration.BasicAuthentication(),
null,
true,
)
Xml.write(Serializer.serialize(cfg), System.out)
}
@@ -67,7 +73,7 @@ class BasicAuthServerTest : AbstractServerTest() {
}
fun newRequestBuilder(key : String) = HttpRequest.newBuilder()
.uri(URI.create("http://${cfg.host}:${cfg.port}/$key"))
.uri(URI.create("http://${cfg.host}:${cfg.port}/$serverPath/$key"))
fun newEntry(random : Random) : Pair<String, ByteArray> {

View File

@@ -1,32 +1,44 @@
package net.woggioni.gbcs.test
import net.woggioni.gbcs.configuration.Configuration
import net.woggioni.gbcs.GradleBuildCacheServer
import net.woggioni.gbcs.Xml
import net.woggioni.gbcs.base.GBCS.toUrl
import net.woggioni.gbcs.base.Xml
import net.woggioni.gbcs.configuration.Parser
import net.woggioni.gbcs.configuration.Serializer
import net.woggioni.gbcs.url.ClasspathUrlStreamHandlerFactoryProvider
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.io.TempDir
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.ValueSource
import java.net.URL
import java.nio.file.Files
import java.nio.file.Path
class ConfigurationTest {
class ConfigurationTestKt {
@Test
fun test(@TempDir testDir : Path) {
URL.setURLStreamHandlerFactory(ClasspathUrlStreamHandlerFactoryProvider())
val dbf = Xml.newDocumentBuilderFactory(GradleBuildCacheServer.CONFIGURATION_SCHEMA_URL)
val db = dbf.newDocumentBuilder()
val configurationUrl = GradleBuildCacheServer.DEFAULT_CONFIGURATION_URL
val doc = configurationUrl.openStream().use(db::parse)
val cfg = Configuration.parse(doc)
// companion object {
// init {
// URL.setURLStreamHandlerFactory(ClasspathUrlStreamHandlerFactoryProvider())
// }
// }
@ValueSource(
strings = [
"classpath:net/woggioni/gbcs/test/gbcs-default.xml",
"classpath:net/woggioni/gbcs/test/gbcs-memcached.xml",
]
)
@ParameterizedTest
fun test(configurationUrl: String, @TempDir testDir: Path) {
ClasspathUrlStreamHandlerFactoryProvider.install()
val doc = Xml.parseXml(configurationUrl.toUrl())
val cfg = Parser.parse(doc)
val configFile = testDir.resolve("gbcs.xml")
Files.newOutputStream(configFile).use {
Xml.write(Serializer.serialize(cfg), it)
}
val parsed = Configuration.parse(Xml.parseXml(configFile.toUri().toURL()))
Xml.write(Serializer.serialize(cfg), System.out)
val parsed = Parser.parse(Xml.parseXml(configFile.toUri().toURL()))
Assertions.assertEquals(cfg, parsed)
}
}

View File

@@ -1,8 +1,9 @@
package net.woggioni.gbcs.test
import io.netty.handler.codec.http.HttpResponseStatus
import net.woggioni.gbcs.Xml
import net.woggioni.gbcs.configuration.Configuration
import net.woggioni.gbcs.base.Xml
import net.woggioni.gbcs.api.Configuration
import net.woggioni.gbcs.cache.FileSystemCacheConfiguration
import net.woggioni.gbcs.configuration.Serializer
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Order
@@ -15,28 +16,36 @@ import java.net.http.HttpResponse
import java.nio.file.Path
import java.time.Duration
import java.util.Base64
import java.util.zip.Deflater
import kotlin.random.Random
class NoAuthServerTest : AbstractServerTest() {
class NoAuthServerTestKt : AbstractServerTestKt() {
private lateinit var cacheDir : Path
private val random = Random(101325)
private val keyValuePair = newEntry(random)
private val serverPath = "/some/nested/path"
override fun setUp() {
this.cacheDir = testDir.resolve("cache")
cfg = Configuration.of(
cache = Configuration.FileSystemCache(this.cacheDir, maxAge = Duration.ofSeconds(3600 * 24)),
host = "127.0.0.1",
port = ServerSocket(0).localPort + 1,
users = emptyMap(),
groups = emptyMap(),
authentication = null,
useVirtualThread = true,
tls = null,
serverPath = "/"
cfg = Configuration(
"127.0.0.1",
ServerSocket(0).localPort + 1,
serverPath,
emptyMap(),
emptyMap(),
FileSystemCacheConfiguration(
this.cacheDir,
maxAge = Duration.ofSeconds(3600 * 24),
compressionEnabled = true,
digestAlgorithm = "MD5",
compressionLevel = Deflater.DEFAULT_COMPRESSION
),
null,
null,
true,
)
Xml.write(Serializer.serialize(cfg), System.out)
}
@@ -45,7 +54,7 @@ class NoAuthServerTest : AbstractServerTest() {
}
fun newRequestBuilder(key : String) = HttpRequest.newBuilder()
.uri(URI.create("http://${cfg.host}:${cfg.port}/$key"))
.uri(URI.create("http://${cfg.host}:${cfg.port}/$serverPath/$key"))
fun newEntry(random : Random) : Pair<String, ByteArray> {
val key = ByteArray(0x10).let {

View File

@@ -1,9 +1,10 @@
package net.woggioni.gbcs.test
import io.netty.handler.codec.http.HttpResponseStatus
import net.woggioni.gbcs.Role
import net.woggioni.gbcs.Xml
import net.woggioni.gbcs.configuration.Configuration
import net.woggioni.gbcs.api.Configuration
import net.woggioni.gbcs.api.Role
import net.woggioni.gbcs.base.Xml
import net.woggioni.gbcs.cache.FileSystemCacheConfiguration
import net.woggioni.gbcs.configuration.Serializer
import net.woggioni.gbcs.utils.CertificateUtils
import net.woggioni.gbcs.utils.CertificateUtils.X509Credentials
@@ -23,19 +24,23 @@ import java.security.KeyStore
import java.security.KeyStore.PasswordProtection
import java.time.Duration
import java.util.Base64
import java.util.zip.Deflater
import javax.net.ssl.KeyManagerFactory
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManagerFactory
import kotlin.random.Random
class TlsServerTest : AbstractServerTest() {
class TlsServerTestKt : AbstractServerTestKt() {
companion object {
private const val CA_CERTIFICATE_ENTRY = "gbcs-ca"
private const val CLIENT_CERTIFICATE_ENTRY = "gbcs-client"
private const val SERVER_CERTIFICATE_ENTRY = "gbcs-server"
private const val PASSWORD = "password"
// private fun stripLeadingSlash(s : String) = Path.of("/").root.relativize(Path.of(s).normalize()).toString()
}
private lateinit var cacheDir: Path
@@ -51,6 +56,7 @@ class TlsServerTest : AbstractServerTest() {
private val writersGroup = Configuration.Group("writers", setOf(Role.Writer))
private val random = Random(101325)
private val keyValuePair = newEntry(random)
private val serverPath : String? = null
private val users = listOf(
Configuration.User("user1", null, setOf(readersGroup)),
@@ -104,7 +110,7 @@ class TlsServerTest : AbstractServerTest() {
}
}
fun getClientKeyStore(ca : X509Credentials, subject: X500Name) = KeyStore.getInstance("PKCS12").apply {
fun getClientKeyStore(ca: X509Credentials, subject: X500Name) = KeyStore.getInstance("PKCS12").apply {
val clientCert = CertificateUtils.createClientCertificate(ca, subject, 30)
load(null, null)
@@ -116,7 +122,7 @@ class TlsServerTest : AbstractServerTest() {
)
}
fun getHttpClient(clientKeyStore : KeyStore?): HttpClient {
fun getHttpClient(clientKeyStore: KeyStore?): HttpClient {
val kmf = clientKeyStore?.let {
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()).apply {
init(it, PASSWORD.toCharArray())
@@ -141,23 +147,28 @@ class TlsServerTest : AbstractServerTest() {
this.trustStoreFile = testDir.resolve("truststore.p12")
this.cacheDir = testDir.resolve("cache")
createKeyStoreAndTrustStore()
cfg = Configuration.of(
cache = Configuration.FileSystemCache(this.cacheDir, maxAge = Duration.ofSeconds(3600 * 24)),
host = "127.0.0.1",
port = ServerSocket(0).localPort + 1,
users = users.asSequence().map { it.name to it }.toMap(),
groups = sequenceOf(writersGroup, readersGroup).map { it.name to it }.toMap(),
authentication = Configuration.ClientCertificateAuthentication(
userExtractor = Configuration.TlsCertificateExtractor("CN", "(.*)"),
groupExtractor = null
cfg = Configuration(
"127.0.0.1",
ServerSocket(0).localPort + 1,
serverPath,
users.asSequence().map { it.name to it }.toMap(),
sequenceOf(writersGroup, readersGroup).map { it.name to it }.toMap(),
FileSystemCacheConfiguration(this.cacheDir,
maxAge = Duration.ofSeconds(3600 * 24),
compressionEnabled = true,
compressionLevel = Deflater.DEFAULT_COMPRESSION,
digestAlgorithm = "MD5"
),
useVirtualThread = true,
tls = Configuration.Tls(
Configuration.ClientCertificateAuthentication(
Configuration.TlsCertificateExtractor("CN", "(.*)"),
null
),
Configuration.Tls(
Configuration.KeyStore(this.serverKeyStoreFile, null, SERVER_CERTIFICATE_ENTRY, PASSWORD),
Configuration.TrustStore(this.trustStoreFile, null, false),
true
),
serverPath = "/"
false,
)
Xml.write(Serializer.serialize(cfg), System.out)
}
@@ -166,7 +177,7 @@ class TlsServerTest : AbstractServerTest() {
}
fun newRequestBuilder(key: String) = HttpRequest.newBuilder()
.uri(URI.create("https://${cfg.host}:${cfg.port}/$key"))
.uri(URI.create("https://${cfg.host}:${cfg.port}/${serverPath ?: ""}/$key"))
fun buildAuthorizationHeader(user: Configuration.User, password: String): String {
val b64 = Base64.getEncoder().encode("${user.name}:${password}".toByteArray(Charsets.UTF_8)).let {

View File

@@ -4,7 +4,7 @@ import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Test
import javax.naming.ldap.LdapName
class X500NameTest {
class X500NameTestKt {
@Test
fun test() {

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<gbcs:server useVirtualThreads="false" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xmlns:gbcs="urn:net.woggioni.gbcs"
xs:schemaLocation="urn:net.woggioni.gbcs classpath:net/woggioni/gbcs/schema/gbcs.xsd">
<bind host="127.0.0.1" port="11443"/>
<cache xs:type="gbcs:fileSystemCacheType" path="/tmp/gbcs" max-age="P7D"/>
<authentication>
<none/>
</authentication>
</gbcs:server>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<gbcs:server useVirtualThreads="false" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
xmlns:gbcs="urn:net.woggioni.gbcs"
xmlns:gbcs-memcached="urn:net.woggioni.gbcs-memcached"
xs:schemaLocation="urn:net.woggioni.gbcs classpath:net/woggioni/gbcs/schema/gbcs.xsd urn:net.woggioni.gbcs-memcached classpath:net/woggioni/gbcs/memcached/schema/gbcs-memcached.xsd">
<bind host="127.0.0.1" port="11443" />
<cache xs:type="gbcs-memcached:memcachedCacheType" max-age="P7D" max-size="101325" compression-mode="gzip" digest="SHA-256">
<server host="127.0.0.1" port="11211"/>
</cache>
<authentication>
<none/>
</authentication>
</gbcs:server>