Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stats collector; kotlin; mcumgr test mock framework #65

Merged
merged 14 commits into from
Feb 28, 2020

Conversation

bgiori
Copy link
Contributor

@bgiori bgiori commented Feb 21, 2020

This PR is already large enough without refactoring a bit. So I will hold that to later changes when all the other mcumgr group managers are mocked out and tests added.

Adds the stats collector under the managers/meta package. This class is used to more-easily collect one or more statistics groups.

The stats collector test comes with a simple mock transport which implements a regular server behavior. This mock transport currently only implements the stats group commands, but additional handlers are planned to test other group managers.

@codecov
Copy link

codecov bot commented Feb 24, 2020

Codecov Report

❗ No coverage uploaded for pull request base (master@e123e66). Click here to learn what that means.
The diff coverage is 41.66%.

Impacted file tree graph

@@           Coverage Diff            @@
##             master     #65   +/-   ##
========================================
  Coverage          ?   13.1%           
  Complexity        ?      92           
========================================
  Files             ?      60           
  Lines             ?    1869           
  Branches          ?     179           
========================================
  Hits              ?     245           
  Misses            ?    1596           
  Partials          ?      28
Impacted Files Coverage Δ Complexity Δ
...untime/mcumgr/managers/meta/StatisticsCollector.kt 73.91% <100%> (ø) 5 <0> (?)
...ore/src/main/java/io/runtime/mcumgr/util/CBOR.java 37.5% <39.13%> (ø) 5 <5> (?)

Copy link
Contributor

@twyatt twyatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a rather large PR with big changes making it hard to give it a good critique.

The title implies that it could've been broken out into 3 different PRs:

  • Stats collector
  • kotlin
  • mcumgr test mock framework

mcumgr-core/build.gradle Outdated Show resolved Hide resolved
mcumgr-core/build.gradle Outdated Show resolved Hide resolved
mcumgr-core/build.gradle Outdated Show resolved Hide resolved
/**
* List the stat group names from the device and collect each which intersects with the filter.
*/
fun collectAll(filter: Set<String>? = null, callback: StatCollectionCallback): Cancellable {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You pulled in the Coroutines dependency but then utilizing legacy data flow paradigms. Is it because tools that rely on this library don't support modern data flow?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The coroutines is currently used in the unit tests, I can make it a testImplemetation

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason why the external API is not coroutines is to allow for people to use the traditional callbacks if they want (like we do...). Building coroutines support on top of this API would be very simple needed.

Copy link
Contributor

@twyatt twyatt Feb 25, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the plan is to make Coroutines a first class citizen, then perhaps it would be better to use Coroutines in the library then provide an "extension" library that wraps the Coroutine versions to provide the callback implementation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would love to have coroutines as a first-class citizen. The issue I see is that the current architecture for mcumgr does not include it whatsoever; so any coroutines addition to the current major version 0.x.x would simply be at a wrapping-api level. The crux of coroutine support would be at the transport interface.

I think we should plan a v1.x.x with coroutines built in all the way down to the transport interface and beyond, with a callback based api-wrapper (essentially the opposite of what we would do now).

In the end, I think adding corountes would be great, just not so in this PR.

mcumgr-core/build.gradle Outdated Show resolved Hide resolved
mcumgr-core/src/main/java/io/runtime/mcumgr/util/CBOR.java Outdated Show resolved Hide resolved
@bgiori
Copy link
Contributor Author

bgiori commented Feb 25, 2020

This is a rather large PR with big changes making it hard to give it a good critique.

The title implies that it could've been broken out into 3 different PRs:

  • Stats collector
  • kotlin
  • mcumgr test mock framework

The reason it's all in one is because each relies on another. In order to add the stats collector, we need kotlin support, and generally I would add the tests for a certain feature with the PR where that feature is added.

So if we split it out we would have a few line PR to add kotlin w/out any kotlin code in the repo, then a PR to add the stats collector, then a PR to add the stats collector tests -- Each relying on the one before.

You seemed to have gone through most of it ok.

@bgiori
Copy link
Contributor Author

bgiori commented Feb 25, 2020

@twyatt Also, this is all already in the gateway SDK. I just wanted to pull it out into here for external use and as a base for additional unit tests.

@bgiori bgiori requested a review from twyatt February 25, 2020 23:53
@bgiori bgiori merged commit e2e062b into master Feb 28, 2020
Copy link
Contributor

@twyatt twyatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was is the middle of reviewing when this was merged, so I'll just post these comments and you can take them or leave em.

@@ -26,19 +27,24 @@ android {

dependencies {

// Kotlin
implementation "androidx.core:core-ktx:1.2.0"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

@Test
fun `parse image without protected tlvs success`() {
val inputStream = this::class.java.classLoader?.getResourceAsStream("slinky-no-prot-tlv.img")!!
?: throw IllegalStateException("input stream is null")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
?: throw IllegalStateException("input stream is null")

Comment on lines +20 to +21
val inputStream = this::class.java.classLoader?.getResourceAsStream("slinky-prot-tlv.img")
?: throw IllegalStateException("input stream is null")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick

Suggested change
val inputStream = this::class.java.classLoader?.getResourceAsStream("slinky-prot-tlv.img")
?: throw IllegalStateException("input stream is null")
val inputStream = this::class.java.classLoader?.getResourceAsStream("slinky-prot-tlv.img")!!

Comment on lines +12 to +14
val inputStream = this::class.java.classLoader?.getResourceAsStream("slinky-no-prot-tlv.img")!!
?: throw IllegalStateException("input stream is null")
val imageData = toByteArray(inputStream)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: could make these more readable with a quick refactor.

fun String.readByteArray() =
    McuMgrImageTest::class.java.classLoader!!
        .getResourceAsStream(this)
        .toByteArray()
Suggested change
val inputStream = this::class.java.classLoader?.getResourceAsStream("slinky-no-prot-tlv.img")!!
?: throw IllegalStateException("input stream is null")
val imageData = toByteArray(inputStream)
val imageData = "slinky-no-prot-tlv.img".readByteArray()

Comment on lines +26 to +30
private fun toByteArray(inputStream: InputStream): ByteArray {
val os = ByteArrayOutputStream()
val buffer = ByteArray(1024)
var len: Int
while (inputStream.read(buffer).also { len = it } != -1) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick

Suggested change
private fun toByteArray(inputStream: InputStream): ByteArray {
val os = ByteArrayOutputStream()
val buffer = ByteArray(1024)
var len: Int
while (inputStream.read(buffer).also { len = it } != -1) {
private fun InputStream.toByteArray(): ByteArray {
val os = ByteArrayOutputStream()
val buffer = ByteArray(1024)
var len: Int
while (read(buffer).also { len = it } != -1) {

Comment on lines +1 to +35
package io.runtime.mcumgr

import io.runtime.mcumgr.image.McuMgrImage
import org.junit.Test
import java.io.ByteArrayOutputStream
import java.io.InputStream

class McuMgrImageTest {

@Test
fun `parse image without protected tlvs success`() {
val inputStream = this::class.java.classLoader?.getResourceAsStream("slinky-no-prot-tlv.img")!!
?: throw IllegalStateException("input stream is null")
val imageData = toByteArray(inputStream)
McuMgrImage.fromBytes(imageData)
}

@Test
fun `parse image with protected tlvs success`() {
val inputStream = this::class.java.classLoader?.getResourceAsStream("slinky-prot-tlv.img")
?: throw IllegalStateException("input stream is null")
val imageData = toByteArray(inputStream)
McuMgrImage.fromBytes(imageData)
}

private fun toByteArray(inputStream: InputStream): ByteArray {
val os = ByteArrayOutputStream()
val buffer = ByteArray(1024)
var len: Int
while (inputStream.read(buffer).also { len = it } != -1) {
os.write(buffer, 0, len)
}
return os.toByteArray()
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For readability, the combination of the above suggestions:

class McuMgrImageTest {

    @Test
    fun `parse image without protected tlvs success`() {
        McuMgrImage.fromBytes("slinky-no-prot-tlv.img".readByteArray())
    }

    @Test
    fun `parse image with protected tlvs success`() {
        McuMgrImage.fromBytes("slinky-prot-tlv.img".readByteArray())
    }
}

private fun String.readByteArray() =
    McuMgrImageTest::class.java.classLoader!!
        .getResourceAsStream(this)
        .toByteArray()

private fun InputStream.toByteArray(): ByteArray {
    val os = ByteArrayOutputStream()
    val buffer = ByteArray(1024)
    var len: Int
    while (read(buffer).also { len = it } != -1) {
        os.write(buffer, 0, len)
    }
    return os.toByteArray()
}

package io.runtime.mcumgr

import io.runtime.mcumgr.image.McuMgrImage
import org.junit.Test
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import org.junit.Test
import kotlin.test.Test

@bgiori
Copy link
Contributor Author

bgiori commented Feb 28, 2020

Was is the middle of reviewing when this was merged, so I'll just post these comments and you can take them or leave em.

Ah sorry! Thanks! I will be making changes to build out the mock transport to support other groups and will take these comments into consideration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants