Skip to content

Commit

Permalink
KLogContext compilation test (#9)
Browse files Browse the repository at this point in the history
* Add TemplateContext and related classes

* Add TemplateContext and associated classes to LogContext

* Add MessageParser and DateTimeFormat tests

* Add IgnoreIos annotation to skip tests running on iOS (iOS is not implemented yet and would fail)

* Finish adding tests

* Add KLogContext not crashing test

* Formatting
  • Loading branch information
buenaflor committed Aug 3, 2023
1 parent 104f015 commit db0ba69
Show file tree
Hide file tree
Showing 12 changed files with 308 additions and 90 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ public expect abstract class KLogContext<LOGGER : KAbstractLogger<API>, API : KL
*/
protected abstract fun noOp(): API

/** Returns the msg parser used for all log statements made through this logger. */
protected abstract fun getMessageParser(): KMessageParser?
/** Returns the message parser used for all log statements made through this logger. */
protected abstract fun getMessageParser(): KMessageParser

// ---- LogData API ----

Expand Down
57 changes: 29 additions & 28 deletions api/src/commonMain/kotlin/com/buenaflor/kflogger/KLogSite.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,36 @@ package com.buenaflor.kflogger
* `StackTraceElement`, this log site will not be unique if multiple log statements are on the the
* same, or if line number information was stripped from the class file.
*/
public expect abstract class KLogSite : KLogSiteKey {
public expect abstract class KLogSite() : KLogSiteKey {
// Provide a common toString() implementation for only the public attributes.
public override final fun toString(): String
public final override fun toString(): String

/** Returns the name of the class containing the log statement. */
public abstract fun getClassName(): String

/** Returns the name of the method containing the log statement. */
public abstract fun getMethodName(): String

/**
* Returns a valid line number for the log statement in the range 1 - 65535, or [.UNKNOWN_LINE] if
* not known.
*
* There is a limit of 16 bits for line numbers in a class. See
* [here](http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.12) for more
* details.
*/
public abstract fun getLineNumber(): Int

/**
* Returns the name of the class file containing the log statement (or null if not known). The
* source file name is optional and strictly for debugging.
*
* Normally this value (if present) is extracted from the SourceFile attribute of the class file
* (see the
* [JVM class file format specification](https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.10)
* for more details).
*/
public abstract fun getFileName(): String

public companion object {
/** A value used for line numbers when the true information is not available. */
Expand Down Expand Up @@ -64,29 +91,3 @@ public expect abstract class KLogSite : KLogSiteKey {
): KLogSite
}
}

/** Returns the name of the class containing the log statement. */
public expect val KLogSite.className: String?

/** Returns the name of the method containing the log statement. */
public expect val KLogSite.methodName: String?

/**
* Returns a valid line number for the log statement in the range 1 - 65535, or [.UNKNOWN_LINE] if
* not known.
*
* There is a limit of 16 bits for line numbers in a class. See
* [here](http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.12) for more
* details.
*/
public expect val KLogSite.lineNumber: Int

/**
* Returns the name of the class file containing the log statement (or null if not known). The
* source file name is optional and strictly for debugging.
*
* <p>Normally this value (if present) is extracted from the SourceFile attribute of the class file
* (see the <a href="https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.10">JVM
* class file format specification</a> for more details).
*/
public expect val KLogSite.fileName: String?
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ package com.buenaflor.kflogger
* different providers can provide different types of scope (e.g. you can have a provider for
* "request" scopes and a provider for "sub-task" scopes)
*/
public expect interface KLoggingScopeProvider

public expect val KLoggingScopeProvider.currentScope: KLoggingScope?
public expect interface KLoggingScopeProvider {
/**
* Returns the current scope (most likely via global or thread local state) or `null` if there is
* no current scope.
*/
public fun getCurrentScope(): KLoggingScope?
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ public expect abstract class KLoggerBackend() {
* @throws LoggingException to indicate an error which should be propagated into user code.
*/
public abstract fun handleError(error: RuntimeException, badData: KLogData)
}

/** Returns the logger name (which is usually a canonicalized class name) or `null` if not given. */
public expect val KLoggerBackend.loggerName: String?
/**
* Returns the logger name (which is usually a canonicalized class name) or `null` if not given.
*/
public abstract fun getLoggerName(): String
}
228 changes: 228 additions & 0 deletions api/src/commonTest/kotlin/com.buenaflor.kflogger/KLogContextTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
package com.buenaflor.kflogger

import com.buenaflor.kflogger.backend.KLogData
import com.buenaflor.kflogger.backend.KLoggerBackend
import com.buenaflor.kflogger.backend.metadata
import com.buenaflor.kflogger.parser.KMessageBuilder
import com.buenaflor.kflogger.parser.KMessageParser
import com.buenaflor.kflogger.util.IgnoreIos
import kotlin.test.Test

class KLogContextTest {
// Note: CompileOnly classes do not represent correct functionality but only deal with testing the
// compilation.

abstract class CompileOnlyLogContext<LOGGER : KAbstractLogger<API>, API : KLoggingApi<API>> :
KLogContext<LOGGER, API>(KLevel.WARNING, false)

class CompileOnlyBackend : KLoggerBackend() {
override fun isLoggable(lvl: KLevel): Boolean {
return true
}

override fun log(data: KLogData?) {}

override fun handleError(error: RuntimeException, badData: KLogData) {}

override fun getLoggerName(): String {
return ""
}
}

class CompileOnlyLogger : KAbstractLogger<CompileOnlyLogger.Api>(CompileOnlyBackend()) {
interface Api : KLoggingApi<Api>

class NoOp : KLoggingApiNoOp<Api>(), Api

override fun at(level: KLevel?): Api {
return NoOp()
}
}

class CompileOnlyMessageParser : KMessageParser() {
override fun <T> parseImpl(builder: KMessageBuilder<T>?) {}

override fun unescape(out: StringBuilder?, message: String?, start: Int, end: Int) {}
}

class CompileOnlyContext : CompileOnlyLogContext<CompileOnlyLogger, CompileOnlyLogger.Api>() {
override fun api(): CompileOnlyLogger.Api {
return CompileOnlyLogger().atFine()
}

override fun getLogger(): CompileOnlyLogger {
return CompileOnlyLogger()
}

override fun noOp(): CompileOnlyLogger.Api {
return CompileOnlyLogger().atFine()
}

override fun getMessageParser(): KMessageParser {
return CompileOnlyMessageParser()
}
}

class CompileOnlyLoggingScopeProvider : KLoggingScopeProvider {
override fun getCurrentScope(): KLoggingScope? {
return null
}
}

class CompileOnlyLogPerBucketingStrategy : KLogPerBucketingStrategy<String>("") {
override fun apply(key: String): Any? {
return null
}
}

class CompileOnlyLogSite : KLogSite() {
override fun getClassName(): String {
return ""
}

override fun getMethodName(): String {
return ""
}

override fun getLineNumber(): Int {
return 0
}

override fun getFileName(): String {
return ""
}
}

@Test
@IgnoreIos
fun testNotCrashing() {
// This test is to ensure that the code compiles and does not crash.
val context = CompileOnlyContext()
context.logVarargs("", arrayOf("", 0))
context.log()
context.log("")
context.log("", 0)
context.log("", 0, 0)
context.log("", 0, 0, 0)
context.log("", 0, 0, 0, 0)
context.log("", 0, 0, 0, 0, 0)
context.log("", 0, 0, 0, 0, 0, 0)
context.log("", 0, 0, 0, 0, 0, 0, 0)
context.log("", 0, 0, 0, 0, 0, 0, 0, 0)
context.log("", 0, 0, 0, 0, 0, 0, 0, 0, 0)
context.log("", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
context.log("", 0.toChar())
context.log("", 0.toByte())
context.log("", 0.toShort())
context.log("", 0)
context.log("", 0L)
context.log("", 0, true)
context.log("", 0.toChar(), true)
context.log("", 0.toByte(), true)
context.log("", 0.toShort(), true)
context.log("", 0, true)
context.log("", 0L, true)
context.log("", 0F, true)
context.log("", 0.0, true)
context.log("", true, 0)
context.log("", true, 0.toChar())
context.log("", true, 0.toByte())
context.log("", true, 0.toShort())
context.log("", true, 0)
context.log("", true, 0L)
context.log("", true, 0F)
context.log("", true, 0.0)
context.log("", true, true)
context.log("", true, 0.toChar())
context.log("", true, 0.toByte())
context.log("", true, 0.toShort())
context.log("", true, 0)
context.log("", true, 0L)
context.log("", true, 0F)
context.log("", true, 0.0)
context.log("", true, 'a')
context.log("", 'a', 'a')
context.log("", 'a', 0.toByte())
context.log("", 'a', 0.toShort())
context.log("", 'a', 0)
context.log("", 'a', 0L)
context.log("", 'a', 0F)
context.log("", 'a', 0.0)
context.log("", true, 0.toByte())
context.log("", 'a', 0.toByte())
context.log("", 0.toByte(), 0.toByte())
context.log("", 0.toShort(), 0.toByte())
context.log("", 0, 0.toByte())
context.log("", 0L, 0.toByte())
context.log("", 0F, 0.toByte())
context.log("", 0.0, 0.toByte())
context.log("", true, 0.toShort())
context.log("", 'a', 0.toShort())
context.log("", 0.toByte(), 0.toShort())
context.log("", 0.toShort(), 0.toShort())
context.log("", 0, 0.toShort())
context.log("", 0L, 0.toShort())
context.log("", 0F, 0.toShort())
context.log("", 0.0, 0.toShort())
context.log("", true, 0)
context.log("", 'a', 0)
context.log("", 0.toByte(), 0)
context.log("", 0.toShort(), 0)
context.log("", 0, 0)
context.log("", 0L, 0)
context.log("", 0F, 0)
context.log("", 0.0, 0)
context.log("", true, 0L)
context.log("", 'a', 0L)
context.log("", 0.toByte(), 0L)
context.log("", 0.toShort(), 0L)
context.log("", 0, 0L)
context.log("", 0L, 0L)
context.log("", 0F, 0L)
context.log("", 0.0, 0L)
context.log("", true, 0F)
context.log("", 'a', 0F)
context.log("", 0.toByte(), 0F)
context.log("", 0.toShort(), 0F)
context.log("", 0, 0F)
context.log("", 0L, 0F)
context.log("", 0F, 0F)
context.log("", 0.0, 0F)
context.log("", true, 0.0)
context.log("", 'a', 0.0)
context.log("", 0.toByte(), 0.0)
context.log("", 0.toShort(), 0.0)
context.log("", 0, 0.0)
context.log("", 0L, 0.0)
context.log("", 0F, 0.0)
context.log("", 0.0, 0.0)
context.atMostEvery(1, KTimeUnit.SECONDS)
context.every(1)
context.isEnabled()
context.onAverageEvery(1)
context.per(KTimeUnit.SECONDS)
context.per(CompileOnlyLoggingScopeProvider())
context.per("", CompileOnlyLogPerBucketingStrategy())
context.wasForced()
context.with(KLogContextKey.WAS_FORCED, true)
context.withCause(Throwable())
context.withInjectedLogSite(CompileOnlyLogSite())
context.withInjectedLogSite("", "", 0, "")
context.withStackTrace(KStackSize.FULL)
context.arguments
context.level
context.logSite
context.loggerName
context.metadata
context.timestampNanos
context.timestampMicros

KLogContextKey.LOG_CAUSE
KLogContextKey.LOG_EVERY_N
KLogContextKey.CONTEXT_STACK_SIZE
KLogContextKey.LOG_SAMPLE_EVERY_N
KLogContextKey.LOG_SITE_GROUPING_KEY
KLogContextKey.SKIPPED_LOG_COUNT
KLogContextKey.WAS_FORCED
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public actual abstract class KLogContext<LOGGER : KAbstractLogger<API>, API : KL
protected actual abstract fun noOp(): API

/** Returns the message parser used for all log statements made through this logger. */
protected actual abstract fun getMessageParser(): KMessageParser?
protected actual abstract fun getMessageParser(): KMessageParser

// ---- LogData API ----

Expand Down
Loading

0 comments on commit db0ba69

Please sign in to comment.