Skip to content

Commit

Permalink
feature: Limit Maximum Number of Logs
Browse files Browse the repository at this point in the history
Closes: #19
Signed-Off-By: Andre Weber <andre.weber3@etas.com>
  • Loading branch information
wba2hi committed Oct 13, 2023
1 parent bfbdee2 commit 07a808a
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -392,26 +392,30 @@ fun DataBrokerOutput(viewModel: OutputViewModel, modifier: Modifier = Modifier)
val shape = RoundedCornerShape(20.dp, 20.dp, 0.dp, 0.dp)
val scrollState = rememberScrollState(0)

val output = viewModel.output

Surface(
modifier = modifier.height(500.dp),
color = MaterialTheme.colorScheme.primary,
shape = shape,
) {
Column(modifier = Modifier.verticalScroll(scrollState)) {
Headline(name = "Output", color = Color.White)
Text(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth()
.padding(start = DefaultElementPadding, end = DefaultElementPadding),
text = viewModel.output,
textAlign = TextAlign.Start,
onTextLayout = {
scope.launch {
scrollState.animateScrollTo(scrollState.maxValue)
}
},
)
output.forEach { outputElement ->
Text(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth()
.padding(start = DefaultElementPadding, end = DefaultElementPadding),
text = outputElement,
textAlign = TextAlign.Start,
onTextLayout = {
scope.launch {
scrollState.animateScrollTo(scrollState.maxValue)
}
},
)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,30 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import org.eclipse.kuksa.testapp.util.MaxElementSet
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

private const val MAX_NUMBER_LOG_ENTRIES = 100

class OutputViewModel : ViewModel() {
var output: String by mutableStateOf("")
private val maxElementSet = MaxElementSet<String>(MAX_NUMBER_LOG_ENTRIES)

var output: List<String> by mutableStateOf(listOf())
private set

fun appendOutput(text: String) {
val emptyLines = if (output.isEmpty()) "\n" else "\n\n"
val dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")
val emptyLines = if (maxElementSet.isEmpty()) "\n" else "\n\n"
val dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss:SSS")
val date = LocalDateTime.now().format(dateFormatter)
output += "$emptyLines- $date\n $text"
maxElementSet += "$emptyLines- $date\n $text"

output = maxElementSet.toList()
}

fun clear() {
output = ""
maxElementSet.clear()

output = maxElementSet.toList()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright (c) 2023 Contributors to the Eclipse Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/

package org.eclipse.kuksa.testapp.util

class MaxElementSet<T>(private val maxNumberEntries: Int = Int.MAX_VALUE) : MutableSet<T> {

private val map: LinkedHashMap<T, Boolean> = object : LinkedHashMap<T, Boolean>() {
override fun removeEldestEntry(eldest: MutableMap.MutableEntry<T, Boolean>?): Boolean {
return size > maxNumberEntries
}
}

override val size: Int
get() = map.size

override fun contains(element: T): Boolean {
return map[element] == true
}

override fun containsAll(elements: Collection<T>): Boolean {
var containsAll = true
elements.forEach { element ->
containsAll = containsAll && contains(element)
}
return containsAll
}

override fun add(element: T): Boolean {
map[element] = true
return true
}

override fun addAll(elements: Collection<T>): Boolean {
val associatedElements = elements.associateWith { true }

map.putAll(associatedElements)
return true
}

override fun clear() {
map.clear()
}

override fun isEmpty(): Boolean {
return map.isEmpty()
}

override fun iterator(): MutableIterator<T> {
return map.keys.iterator()
}

override fun retainAll(elements: Collection<T>): Boolean {
throw UnsupportedOperationException("not supported")
}

override fun removeAll(elements: Collection<T>): Boolean {
elements.forEach { element ->
map.remove(element)
}
return true
}

override fun remove(element: T): Boolean {
return map.remove(element) != null
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright (c) 2023 Contributors to the Eclipse Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*
*/

package org.eclipse.kuksa.testapp.util

import io.kotest.core.spec.style.BehaviorSpec
import io.kotest.matchers.shouldBe

class MaxElementSetTest : BehaviorSpec({
given("An Instance of MaxElementSet with Type TestElement and maxNumberEntries of 100") {
val classUnderTest = MaxElementSet<TestElement>(100)

`when`("Adding 100 elements") {
val testElements = mutableListOf<TestElement>()
repeat(100) {
val testElement = TestElement()

testElements.add(testElement)
classUnderTest.add(testElement)
}

then("All 100 elements are added successfully") {
classUnderTest.size shouldBe 100
}

then("The order is kept intact") {
classUnderTest.withIndex().forEach {
val index = it.index
val value = it.value

value shouldBe testElements[index]
}
}
}
}

given("An Instance of MaxElementSet with Type TestElement and maxNumberEntries of 10") {
val classUnderTest = MaxElementSet<TestElement>(10)

`when`("Trying to add the same element twice") {
val testElement = TestElement()
classUnderTest.add(testElement)
classUnderTest.add(testElement)

then("It is only added once") {
classUnderTest.size shouldBe 1
}
}

`when`("Adding more than 10 elements (100)") {
val testElements = mutableListOf<TestElement>()
repeat(100) {
val testElement = TestElement()

testElements.add(testElement)
classUnderTest.add(testElement)
}

then("Only the last 10 Elements are kept") {
classUnderTest.size shouldBe 10

val subList = testElements.subList(90, 100)
val containsLastTenElements = classUnderTest.containsAll(subList)
containsLastTenElements shouldBe true
}
}
}
})

class TestElement

0 comments on commit 07a808a

Please sign in to comment.