Moved from Gradle to bld

This commit is contained in:
Erik C. Thauvin 2023-11-10 23:43:20 -08:00
parent 1cd7c5a79e
commit c68c25aa95
240 changed files with 11508 additions and 1650 deletions

67
bin/test/current.xml Normal file
View file

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ current.xml
~
~ Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
~
~ Redistribution and use in source and binary forms, with or without
~ modification, are permitted provided that the following conditions are met:
~
~ Redistributions of source code must retain the above copyright notice, this
~ list of conditions and the following disclaimer.
~
~ Redistributions in binary form must reproduce the above copyright notice,
~ this list of conditions and the following disclaimer in the documentation
~ and/or other materials provided with the distribution.
~
~ Neither the name of this project nor the names of its contributors may be
~ used to endorse or promote products derived from this software without
~ specific prior written permission.
~
~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
~ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
~ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
~ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
~ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
~ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
~ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
~ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
~ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
~ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
<channel>
<title>#mobibot IRC Links</title>
<link>https://www.mobitopia.org/mobibot/logs</link>
<description>Links from irc.example.com on #mobibot</description>
<language>en</language>
<pubDate>Sun, 31 Oct 2021 21:45:11 GMT</pubDate>
<dc:date>2021-10-31T21:45:11Z</dc:date>
<dc:language>en</dc:language>
<item>
<title>Example 2</title>
<link>https://www.example.com/2</link>
<description>Posted by &lt;b&gt;Skynx&lt;/b&gt; on &lt;a href="irc://irc.libera.chat/#mobibot"&gt;&lt;b&gt;#mobibot&lt;/b&gt;&lt;/a&gt;</description>
<category>tag2-1</category>
<category>tag2-2</category>
<pubDate>Sun, 31 Oct 2021 21:45:11 GMT</pubDate>
<guid>https://www.foo.com</guid>
<dc:creator>mobibot@irc.libera.chat (Skynx)</dc:creator>
<dc:date>2021-10-31T00:01:00Z</dc:date>
</item>
<item>
<title>Example 1</title>
<link>https://www.example.com/1</link>
<description>Posted by &lt;b&gt;ErikT&lt;/b&gt; on &lt;a href="irc://irc.libera.chat/#mobibot"&gt;&lt;b&gt;#mobibot&lt;/b&gt;&lt;/a&gt;
&lt;br/&gt;&lt;br/&gt;ErikT: This is comment 1. &lt;br/&gt;Skynx: This is comment 2.
</description>
<category>tag1-1</category>
<category>tag1-2</category>
<pubDate>Sun, 31 Oct 2021 21:43:15 GMT</pubDate>
<guid>https://www.example.com/</guid>
<dc:creator>mobibot@irc.libera.chat (ErikT)</dc:creator>
<dc:date>2021-10-31T00:00:00Z</dc:date>
</item>
</channel>
</rss>

View file

@ -0,0 +1,86 @@
/*
* AddonsTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot
import assertk.assertThat
import assertk.assertions.containsExactly
import assertk.assertions.isEqualTo
import assertk.assertions.size
import net.thauvin.erik.mobibot.commands.ChannelFeed
import net.thauvin.erik.mobibot.commands.Cycle
import net.thauvin.erik.mobibot.commands.Die
import net.thauvin.erik.mobibot.commands.Ignore
import net.thauvin.erik.mobibot.commands.links.Comment
import net.thauvin.erik.mobibot.commands.links.View
import net.thauvin.erik.mobibot.modules.*
import kotlin.test.Test
import java.util.*
class AddonsTest {
private val p = Properties().apply {
put("disabled-modules", "war,dice Lookup")
put("disabled-commands", "View | comment")
}
private val addons = Addons(p)
@Test
fun addTest() {
// Modules
addons.add(Joke())
addons.add(RockPaperScissors())
addons.add(War())
addons.add(Dice())
addons.add(Lookup())
assertThat(addons::modules).size().isEqualTo(2)
assertThat(addons.names.modules, "names.modules").containsExactly("Joke", "RockPaperScissors")
// Commands
addons.add(View())
addons.add(Comment())
addons.add(Cycle())
addons.add(Die()) // invisible
addons.add(ChannelFeed("channel")) // no properties, disabled
p[Ignore.IGNORE_PROP] = "nick"
addons.add(Ignore())
assertThat(addons::commands).size().isEqualTo(3)
assertThat(addons.names.ops, "names.ops").containsExactly("cycle")
assertThat(addons.names.commands, "names.command").containsExactly(
"joke",
"rock",
"paper",
"scissors",
"ignore"
)
}
}

View file

@ -0,0 +1,60 @@
/*
* ExceptionSanitizer.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot
import net.thauvin.erik.mobibot.Utils.obfuscate
import net.thauvin.erik.mobibot.Utils.replaceEach
import net.thauvin.erik.mobibot.modules.ModuleException
object ExceptionSanitizer {
/**
* Returns a sanitized exception to avoid displaying api keys, etc. in CI logs.
*/
fun ModuleException.sanitize(vararg sanitize: String): ModuleException {
val search = sanitize.filter { it.isNotBlank() }.toTypedArray()
if (search.isNotEmpty()) {
val obfuscate = search.map { it.obfuscate() }.toTypedArray()
with(this) {
if (!cause?.message.isNullOrBlank()) {
return ModuleException(
debugMessage,
cause?.javaClass?.name + ": " + cause?.message?.replaceEach(search, obfuscate),
this
)
} else if (!message.isNullOrBlank()) {
return ModuleException(debugMessage, message?.replaceEach(search, obfuscate), this)
}
}
}
return this
}
}

View file

@ -0,0 +1,78 @@
/*
* FeedReaderTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot
import assertk.all
import assertk.assertFailure
import assertk.assertThat
import assertk.assertions.*
import com.rometools.rome.io.FeedException
import net.thauvin.erik.mobibot.FeedReader.Companion.readFeed
import net.thauvin.erik.mobibot.msg.Message
import kotlin.test.Test
import java.io.IOException
import java.net.MalformedURLException
import java.net.UnknownHostException
/**
* The `FeedReader Test` class.
*/
class FeedReaderTest {
@Test
fun readFeedTest() {
var messages = readFeed("https://feeds.thauvin.net/ethauvin")
assertThat(messages, "messages").all {
size().isEqualTo(10)
index(1).prop(Message::msg).contains("erik.thauvin.net")
}
messages = readFeed("https://lorem-rss.herokuapp.com/feed?length=0")
assertThat(messages, "messages").index(0).prop(Message::msg).contains("nothing")
messages = readFeed("https://lorem-rss.herokuapp.com/feed?length=84", 42)
assertThat(messages, "messages").size().isEqualTo(84)
messages.forEachIndexed { i, m ->
if (i % 2 == 0) {
assertThat(m, "messages($i)").prop(Message::msg).startsWith("Lorem ipsum")
} else {
assertThat(m, "messages($i)").prop(Message::msg).contains("http://example.com/test/")
}
}
assertFailure { readFeed("blah") }.isInstanceOf(MalformedURLException::class.java)
assertFailure { readFeed("https://www.example.com") }.isInstanceOf(FeedException::class.java)
assertFailure { readFeed("https://www.thauvin.net/foo") }.isInstanceOf(IOException::class.java)
assertFailure { readFeed("https://www.examplesfoo.com/") }.isInstanceOf(UnknownHostException::class.java)
}
}

View file

@ -0,0 +1,85 @@
/*
* LocalProperties.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot
import org.testng.annotations.BeforeSuite
import java.io.IOException
import java.net.InetAddress
import java.net.UnknownHostException
import java.nio.file.Files
import java.nio.file.Paths
import java.util.*
/**
* Access to `local.properties`.
*/
open class LocalProperties {
@BeforeSuite(alwaysRun = true)
fun loadProperties() {
val localPath = Paths.get("local.properties")
if (Files.exists(localPath)) {
try {
Files.newInputStream(localPath).use { stream -> localProps.load(stream) }
} catch (ignore: IOException) {
// Do nothing
}
}
}
companion object {
private val localProps = Properties()
fun getHostName(): String {
val ciName = System.getenv("CI_NAME")
return ciName ?: try {
InetAddress.getLocalHost().hostName
} catch (ignore: UnknownHostException) {
"Unknown Host"
}
}
fun getProperty(key: String): String {
return if (localProps.containsKey(key)) {
localProps.getProperty(key)
} else {
val env = System.getenv(keyToEnv(key))
env?.let {
localProps.setProperty(key, env)
}
env
}
}
private fun keyToEnv(key: String): String {
return key.replace('-', '_').uppercase()
}
}
}

View file

@ -0,0 +1,81 @@
/*
* PinboardTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot
import net.thauvin.erik.mobibot.Utils.encodeUrl
import net.thauvin.erik.mobibot.Utils.reader
import net.thauvin.erik.mobibot.entries.EntryLink
import org.testng.Assert.assertFalse
import org.testng.Assert.assertTrue
import kotlin.test.Test
import java.net.URL
class PinboardTest : LocalProperties() {
private val pinboard = Pinboard()
@Test
fun testPinboard() {
val apiToken = getProperty("pinboard-api-token")
val url = "https://www.example.com/${(1000..5000).random()}"
val ircServer = "irc.test.com"
val entry = EntryLink(url, "Test Example", "ErikT", "", "#mobitopia", listOf("test"))
pinboard.setApiToken(apiToken)
pinboard.addPin(ircServer, entry)
assertTrue(validatePin(apiToken, url = entry.link, entry.title, entry.nick, entry.channel), "addPin")
entry.link = "https://www.example.com/${(5001..9999).random()}"
pinboard.updatePin(ircServer, url, entry)
assertTrue(validatePin(apiToken, url = entry.link, ircServer), "updatePin")
entry.title = "Foo Title"
pinboard.updatePin(ircServer, entry.link, entry)
assertTrue(validatePin(apiToken, url = entry.link, entry.title), "updatePin(${entry.title}")
pinboard.deletePin(entry)
assertFalse(validatePin(apiToken, url = entry.link), "deletePin")
}
private fun validatePin(apiToken: String, url: String, vararg matches: String): Boolean {
val response =
URL("https://api.pinboard.in/v1/posts/get?auth_token=${apiToken}&tag=test&" + url.encodeUrl()).reader().body
matches.forEach {
if (!response.contains(it)) {
return false
}
}
return response.contains(url)
}
}

View file

@ -0,0 +1,278 @@
/*
* UtilsTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot
import assertk.all
import assertk.assertThat
import assertk.assertions.isEqualTo
import assertk.assertions.length
import net.thauvin.erik.mobibot.Utils.appendIfMissing
import net.thauvin.erik.mobibot.Utils.bold
import net.thauvin.erik.mobibot.Utils.capitalise
import net.thauvin.erik.mobibot.Utils.capitalizeWords
import net.thauvin.erik.mobibot.Utils.colorize
import net.thauvin.erik.mobibot.Utils.cyan
import net.thauvin.erik.mobibot.Utils.encodeUrl
import net.thauvin.erik.mobibot.Utils.getIntProperty
import net.thauvin.erik.mobibot.Utils.green
import net.thauvin.erik.mobibot.Utils.helpCmdSyntax
import net.thauvin.erik.mobibot.Utils.helpFormat
import net.thauvin.erik.mobibot.Utils.lastOrEmpty
import net.thauvin.erik.mobibot.Utils.obfuscate
import net.thauvin.erik.mobibot.Utils.plural
import net.thauvin.erik.mobibot.Utils.reader
import net.thauvin.erik.mobibot.Utils.red
import net.thauvin.erik.mobibot.Utils.replaceEach
import net.thauvin.erik.mobibot.Utils.reverseColor
import net.thauvin.erik.mobibot.Utils.toIntOrDefault
import net.thauvin.erik.mobibot.Utils.toIsoLocalDate
import net.thauvin.erik.mobibot.Utils.toUtcDateTime
import net.thauvin.erik.mobibot.Utils.today
import net.thauvin.erik.mobibot.Utils.underline
import net.thauvin.erik.mobibot.Utils.unescapeXml
import net.thauvin.erik.mobibot.msg.Message.Companion.DEFAULT_COLOR
import org.pircbotx.Colors
import org.testng.annotations.BeforeClass
import kotlin.test.Test
import java.io.File
import java.io.IOException
import java.net.URL
import java.time.LocalDateTime
import java.util.*
/**
* The `Utils Test` class.
*/
class UtilsTest {
private val ascii =
" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
private val cal = Calendar.getInstance()
private val localDateTime = LocalDateTime.of(1952, 2, 17, 12, 30, 0)
private val test = "This is a test."
@BeforeClass
fun setUp() {
cal[1952, Calendar.FEBRUARY, 17, 12, 30] = 0
}
@Test
fun testAppendIfMissing() {
val dir = "dir"
val sep = '/'
val url = "https://erik.thauvin.net"
assertThat(dir.appendIfMissing(File.separatorChar), "appendIfMissing(dir)")
.isEqualTo(dir + File.separatorChar)
assertThat(url.appendIfMissing(sep), "appendIfMissing(url)").isEqualTo("$url$sep")
assertThat("$url$sep".appendIfMissing(sep), "appendIfMissing($url$sep)").isEqualTo("$url$sep")
}
@Test
fun testBold() {
assertThat(1.bold(), "bold(1)").isEqualTo(Colors.BOLD + "1" + Colors.BOLD)
assertThat(2L.bold(), "bold(2L)").isEqualTo(Colors.BOLD + "2" + Colors.BOLD)
assertThat(ascii.bold(), "ascii.bold()").isEqualTo(Colors.BOLD + ascii + Colors.BOLD)
assertThat("test".bold(), "test.bold()").isEqualTo(Colors.BOLD + "test" + Colors.BOLD)
}
@Test
fun testCapitalise() {
assertThat("test".capitalise(), "capitalize(test)").isEqualTo("Test")
assertThat("Test".capitalise(), "capitalize(Test)").isEqualTo("Test")
assertThat(test.capitalise(), "capitalize($test)").isEqualTo(test)
assertThat("".capitalise(), "capitalize()").isEqualTo("")
}
@Test
fun textCapitaliseWords() {
assertThat(test.capitalizeWords(), "captiatlizeWords(test)").isEqualTo("This Is A Test.")
assertThat("Already Capitalized".capitalizeWords(), "already capitalized")
.isEqualTo("Already Capitalized")
assertThat(" a test ".capitalizeWords(), "with spaces").isEqualTo(" A Test ")
}
@Test
fun testColorize() {
assertThat(ascii.colorize(Colors.REVERSE), "reverse.colorize()").isEqualTo(
Colors.REVERSE + ascii + Colors.REVERSE
)
assertThat(ascii.colorize(Colors.RED), "red.colorize()")
.isEqualTo(Colors.RED + ascii + Colors.NORMAL)
assertThat(ascii.colorize(Colors.BOLD), "colorized(bold)")
.isEqualTo(Colors.BOLD + ascii + Colors.BOLD)
assertThat(null.colorize(Colors.RED), "null.colorize()").isEqualTo("")
assertThat("".colorize(Colors.RED), "colorize()").isEqualTo("")
assertThat(ascii.colorize(DEFAULT_COLOR), "ascii.colorize()").isEqualTo(ascii)
assertThat(" ".colorize(Colors.NORMAL), "blank.colorize()")
.isEqualTo(Colors.NORMAL + " " + Colors.NORMAL)
}
@Test
fun testCyan() {
assertThat(ascii.cyan()).isEqualTo(Colors.CYAN + ascii + Colors.NORMAL)
}
@Test
fun testEncodeUrl() {
assertThat("Hello Günter".encodeUrl()).isEqualTo("Hello%20G%C3%BCnter")
}
@Test
fun testGetIntProperty() {
val p = Properties()
p["one"] = "1"
p["two"] = "two"
assertThat(p.getIntProperty("one", 9), "getIntProperty(one)").isEqualTo(1)
assertThat(p.getIntProperty("two", 2), "getIntProperty(two)").isEqualTo(2)
assertThat(p.getIntProperty("foo", 3), "getIntProperty(foo)").isEqualTo(3)
}
@Test
fun testGreen() {
assertThat(ascii.green()).isEqualTo(Colors.DARK_GREEN + ascii + Colors.NORMAL)
}
@Test
fun testHelpCmdSyntax() {
val bot = "mobibot"
assertThat(helpCmdSyntax("%c $test %n $test", bot, false), "helpCmdSyntax(private)")
.isEqualTo("$bot: $test $bot $test")
assertThat(helpCmdSyntax("%c %n $test %c $test %n", bot, true), "helpCmdSyntax(public)")
.isEqualTo("/msg $bot $bot $test /msg $bot $test $bot")
}
@Test
fun testHelpFormat() {
assertThat(helpFormat(test, isBold = true, isIndent = false), "helpFormat(bold)")
.isEqualTo("${Colors.BOLD}$test${Colors.BOLD}")
assertThat(helpFormat(test, isBold = false, isIndent = true), "helpFormat(indent)")
.isEqualTo(test.prependIndent())
assertThat(helpFormat(test, isBold = true, isIndent = true), "helpFormat(bold,indent)")
.isEqualTo(test.colorize(Colors.BOLD).prependIndent())
}
@Test
fun testIsoLocalDate() {
assertThat(cal.time.toIsoLocalDate(), "isoLocalDate(date)").isEqualTo("1952-02-17")
assertThat(localDateTime.toIsoLocalDate(), "isoLocalDate(localDate)").isEqualTo("1952-02-17")
}
@Test
fun testLastOrEmpty() {
val two = listOf("1", "2")
assertThat(two.lastOrEmpty(), "lastOrEmpty(1,2)").isEqualTo("2")
val one = listOf("1")
assertThat(one.lastOrEmpty(), "lastOrEmpty(1)").isEqualTo("")
}
@Test
fun testObfuscate() {
assertThat(ascii.obfuscate(), "obfuscate()").all {
length().isEqualTo(ascii.length)
isEqualTo(("x".repeat(ascii.length)))
}
assertThat(" ".obfuscate(), "obfuscate(blank)").isEqualTo(" ")
}
@Test
fun testPlural() {
val week = "week"
val weeks = "weeks"
for (i in -1..3) {
assertThat(week.plural(i.toLong()), "plural($i)").isEqualTo(if (i > 1) weeks else week)
}
}
@Test
fun testReplaceEach() {
val search = arrayOf("one", "two", "three")
val replace = arrayOf("1", "2", "3")
assertThat(search.joinToString(",").replaceEach(search, replace), "replaceEach(1,2,3")
.isEqualTo(replace.joinToString(","))
assertThat(test.replaceEach(search, replace), "replaceEach(nothing)").isEqualTo(test)
assertThat(test.replaceEach(arrayOf("t", "e"), arrayOf("", "E")), "replaceEach($test)")
.isEqualTo(test.replace("t", "").replace("e", "E"))
assertThat(test.replaceEach(search, emptyArray()), "replaceEach(search, empty)")
.isEqualTo(test)
}
@Test
fun testRed() {
assertThat(ascii.red()).isEqualTo(ascii.colorize(Colors.RED))
}
@Test
fun testReverseColor() {
assertThat(ascii.reverseColor()).isEqualTo(Colors.REVERSE + ascii + Colors.REVERSE)
}
@Test
fun testToday() {
assertThat(today()).isEqualTo(LocalDateTime.now().toIsoLocalDate())
}
@Test
fun testToIntOrDefault() {
assertThat("10".toIntOrDefault(1), "toIntOrDefault(10, 1)").isEqualTo(10)
assertThat("a".toIntOrDefault(2), "toIntOrDefault(a, 2)").isEqualTo(2)
}
@Test
fun testUnderline() {
assertThat(ascii.underline()).isEqualTo(ascii.colorize(Colors.UNDERLINE))
}
@Test
fun testUnescapeXml() {
assertThat("&lt;a name=&quot;test &amp; &apos;&#39;&quot;&gt;".unescapeXml()).isEqualTo(
"<a name=\"test & ''\">"
)
}
@Test
@Throws(IOException::class)
fun testUrlReader() {
val reader = URL("https://postman-echo.com/status/200").reader()
assertThat(reader.body).isEqualTo("{\n \"status\": 200\n}")
assertThat(reader.responseCode).isEqualTo(200)
}
@Test
fun testUtcDateTime() {
assertThat(cal.time.toUtcDateTime(), "utcDateTime(date)").isEqualTo("1952-02-17 12:30")
assertThat(localDateTime.toUtcDateTime(), "utcDateTime(localDate)").isEqualTo("1952-02-17 12:30")
}
}

View file

@ -0,0 +1,58 @@
/*
* InfoTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.commands
import assertk.assertThat
import assertk.assertions.isEqualTo
import net.thauvin.erik.mobibot.commands.Info.Companion.toUptime
import kotlin.test.Test
class InfoTest {
@Test
fun testToUptime() {
assertThat(
547800300076L.toUptime(),
"upTime(full)"
).isEqualTo("17 years 4 months 2 weeks 1 day 6 hours 45 minutes")
assertThat(24300000L.toUptime(), "upTime(hours minutes)").isEqualTo("6 hours 45 minutes")
assertThat(110700000L.toUptime(), "upTime(days hours minutes)").isEqualTo("1 day 6 hours 45 minutes")
assertThat(
1320300000L.toUptime(),
"upTime(weeks days hours minutes)"
).isEqualTo("2 weeks 1 day 6 hours 45 minutes")
assertThat(2700000L.toUptime(), "upTime(45 minutes)").isEqualTo("45 minutes")
assertThat(60000L.toUptime(), "upTime(1 minute)").isEqualTo("1 minute")
assertThat(59000L.toUptime(), "upTime(59 seconds)").isEqualTo("59 seconds")
assertThat(0L.toUptime(), "upTime(0 second)").isEqualTo("0 second")
}
}

View file

@ -0,0 +1,60 @@
/*
* RecapTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.commands
import assertk.all
import assertk.assertThat
import assertk.assertions.isEqualTo
import assertk.assertions.matches
import assertk.assertions.prop
import assertk.assertions.size
import kotlin.test.Test
class RecapTest {
@Test
fun storeRecapTest() {
for (i in 1..20) {
Recap.storeRecap("sender$i", "test $i", false)
}
assertThat(Recap.recaps, "Recap.recaps").all {
size().isEqualTo(Recap.MAX_RECAPS)
prop(MutableList<String>::first)
.matches("[1-2]\\d{3}-[01]\\d-[0-3]\\d [0-2]\\d:[0-6]\\d - sender11: test 11".toRegex())
prop(MutableList<String>::last)
.matches("[1-2]\\d{3}-[01]\\d-[0-3]\\d [0-2]\\d:[0-6]\\d - sender20: test 20".toRegex())
}
Recap.storeRecap("sender", "test action", true)
assertThat(Recap.recaps.last())
.matches("[1-2]\\d{3}-[01]\\d-[0-3]\\d [0-2]\\d:[0-6]\\d - sender test action".toRegex())
}
}

View file

@ -0,0 +1,77 @@
/*
* LinksManagerTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.commands.links
import assertk.all
import assertk.assertThat
import assertk.assertions.contains
import assertk.assertions.isEqualTo
import assertk.assertions.isTrue
import assertk.assertions.size
import net.thauvin.erik.mobibot.Constants
import kotlin.test.Test
class LinksManagerTest {
private val linksManager = LinksManager()
@Test
fun fetchTitle() {
assertThat(linksManager.fetchTitle("https://erik.thauvin.net/"), "fetchTitle(Erik)").contains("Erik's Weblog")
assertThat(
linksManager.fetchTitle("https://www.google.com/foo"),
"fetchTitle(Foo)"
).isEqualTo(Constants.NO_TITLE)
}
@Test
fun testMatches() {
assertThat(linksManager.matches("https://www.example.com/"), "matches(url)").isTrue()
assertThat(linksManager.matches("HTTP://erik.thauvin.net/blog/ Erik's Weblog"), "matches(HTTP)").isTrue()
}
@Test
fun matchTagKeywordsTest() {
linksManager.setProperty(LinksManager.KEYWORDS_PROP, "key1 key2,key3")
val tags = mutableListOf<String>()
linksManager.matchTagKeywords("Test title with key2", tags)
assertThat(tags, "tags").contains("key2")
tags.clear()
linksManager.matchTagKeywords("Test key3 title with key1", tags)
assertThat(tags, "tags(key1, key3)").all {
contains("key1")
contains("key3")
size().isEqualTo(2)
}
}
}

View file

@ -0,0 +1,111 @@
/*
* ViewTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.commands.links
import assertk.all
import assertk.assertThat
import assertk.assertions.isEqualTo
import assertk.assertions.prop
import net.thauvin.erik.mobibot.entries.EntryLink
import kotlin.test.Test
class ViewTest {
@Test
fun testParseArgs() {
val view = View()
for (i in 1..10) {
LinksManager.entries.links.add(
EntryLink(
"https://www.example.com/$i",
"Example $i",
"nick$i",
"login$i",
"#channel",
emptyList()
)
)
}
assertThat(view.parseArgs("1"), "parseArgs(1)").all {
prop(Pair<Int, String>::first).isEqualTo(0)
prop(Pair<Int, String>::second).isEqualTo("")
}
assertThat(view.parseArgs("2 foo"), "parseArgs(2, foo)").all {
prop(Pair<Int, String>::first).isEqualTo(1)
prop(Pair<Int, String>::second).isEqualTo("foo")
}
assertThat(view.parseArgs("3 FOO"), "parseArgs(3, FOO)").all {
prop(Pair<Int, String>::first).isEqualTo(2)
prop(Pair<Int, String>::second).isEqualTo("foo")
}
assertThat(view.parseArgs(" 4 foo bar "), "parseArgs( 4 foo bar )").all {
prop(Pair<Int, String>::first).isEqualTo(3)
prop(Pair<Int, String>::second).isEqualTo("foo bar")
}
assertThat(view.parseArgs("foo bar"), "parseArgs(foo bar)").all {
prop(Pair<Int, String>::first).isEqualTo(0)
prop(Pair<Int, String>::second).isEqualTo("foo bar")
}
assertThat(view.parseArgs("${Int.MAX_VALUE}1"), "parseArgs(overflow)").all {
prop(Pair<Int, String>::first).isEqualTo(0)
prop(Pair<Int, String>::second).isEqualTo("${Int.MAX_VALUE}1")
}
assertThat(view.parseArgs("1a"), "parseArgs(1a)").all {
prop(Pair<Int, String>::first).isEqualTo(0)
prop(Pair<Int, String>::second).isEqualTo("1a")
}
assertThat(view.parseArgs("20"), "parseArgs(20)").all {
prop(Pair<Int, String>::first).isEqualTo(0)
prop(Pair<Int, String>::second).isEqualTo("")
}
assertThat(view.parseArgs(""), "parseArgs()").all {
prop(Pair<Int, String>::first).isEqualTo(LinksManager.entries.links.size - View.MAX_ENTRIES)
prop(Pair<Int, String>::second).isEqualTo("")
}
LinksManager.entries.links.clear()
assertThat(view.parseArgs("4"), "parseArgs(4)").all {
prop(Pair<Int, String>::first).isEqualTo(0)
prop(Pair<Int, String>::second).isEqualTo("")
}
}
}

View file

@ -0,0 +1,85 @@
/*
* SeenTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.commands.seen
import assertk.all
import assertk.assertThat
import assertk.assertions.*
import org.testng.annotations.AfterClass
import org.testng.annotations.BeforeClass
import kotlin.test.Test
import kotlin.io.path.deleteIfExists
import kotlin.io.path.fileSize
class SeenTest {
private val tmpFile = kotlin.io.path.createTempFile(suffix = ".ser")
private val seen = Seen(tmpFile.toAbsolutePath().toString())
private val nick = "ErikT"
@BeforeClass
fun saveTest() {
seen.add("ErikT")
assertThat(tmpFile.fileSize(), "tmpFile.size").isGreaterThan(0)
}
@AfterClass(alwaysRun = true)
fun afterClass() {
tmpFile.deleteIfExists()
}
@Test(priority = 1, groups = ["commands"])
fun loadTest() {
seen.clear()
assertThat(seen::seenNicks).isEmpty()
seen.load()
assertThat(seen::seenNicks).key(nick).isNotNull()
}
@Test
fun addTest() {
val last = seen.seenNicks[nick]?.lastSeen
seen.add(nick.lowercase())
assertThat(seen).all {
prop(Seen::seenNicks).size().isEqualTo(1)
prop(Seen::seenNicks).key(nick).isNotNull().prop(SeenNick::lastSeen).isNotEqualTo(last)
prop(Seen::seenNicks).key(nick).isNotNull().prop(SeenNick::nick).isNotNull().isEqualTo(nick.lowercase())
}
}
@Test(priority = 10, groups = ["commands"])
fun clearTest() {
seen.clear()
seen.save()
seen.load()
assertThat(seen::seenNicks).size().isEqualTo(0)
}
}

View file

@ -0,0 +1,72 @@
/*
* TellMessageTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.commands.tell
import assertk.all
import assertk.assertThat
import assertk.assertions.isEqualTo
import assertk.assertions.isFalse
import assertk.assertions.isTrue
import assertk.assertions.prop
import kotlin.test.Test
import java.time.Duration
import java.time.LocalDateTime
import java.time.temporal.Temporal
/**
* The `TellMessageTest` class.
*/
class TellMessageTest {
private fun isValidDate(date: Temporal): Boolean {
return Duration.between(date, LocalDateTime.now()).toMinutes() < 1
}
@Test
fun testTellMessage() {
val message = "Test message."
val recipient = "recipient"
val sender = "sender"
val tellMessage = TellMessage(sender, recipient, message)
assertThat(tellMessage).all {
prop(TellMessage::sender).isEqualTo(sender)
prop(TellMessage::recipient).isEqualTo(recipient)
prop(TellMessage::message).isEqualTo(message)
}
assertThat(isValidDate(tellMessage.queued), "isValidDate()").isTrue()
assertThat(tellMessage.isMatch(sender), "isMatch(sender)").isTrue()
assertThat(tellMessage.isMatch(recipient), "isMatch(recipient)").isTrue()
assertThat(tellMessage.isMatch("foo"), "isMatch(foo)").isFalse()
tellMessage.isReceived = false
assertThat(tellMessage.receptionDate, "receptionDate").isEqualTo(LocalDateTime.MIN)
tellMessage.isReceived = true
assertThat(isValidDate(tellMessage.receptionDate), "isValidDate(creationDate)").isTrue()
}
}

View file

@ -0,0 +1,87 @@
/*
* TellMessagesMgrTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.commands.tell
import assertk.all
import assertk.assertThat
import assertk.assertions.*
import org.testng.annotations.AfterClass
import org.testng.annotations.BeforeClass
import kotlin.test.Test
import java.time.LocalDateTime
import kotlin.io.path.createTempFile
import kotlin.io.path.deleteIfExists
import kotlin.io.path.fileSize
class TellMessagesMgrTest {
private val testFile = createTempFile(suffix = ".ser")
private val maxDays = 10L
private val testMessages = mutableListOf<TellMessage>().apply {
for (i in 0..5) {
this.add(i, TellMessage("sender$i", "recipient$i", "message $i"))
}
}
@BeforeClass
fun saveTest() {
TellManager.save(testFile.toAbsolutePath().toString(), testMessages)
assertThat(testFile.fileSize()).isGreaterThan(0)
}
@AfterClass
fun afterClass() {
testFile.deleteIfExists()
}
@Test
fun cleanTest() {
testMessages.add(TellMessage("sender", "recipient", "message").apply {
queued = LocalDateTime.now().minusDays(maxDays)
})
val size = testMessages.size
assertThat(TellManager.clean(testMessages, maxDays + 2), "clean(maxDays=${maxDays + 2})").isFalse()
assertThat(TellManager.clean(testMessages, maxDays), "clean(maxDays=$maxDays)").isTrue()
assertThat(testMessages, "testMessages").size().isEqualTo(size - 1)
}
@Test
fun loadTest() {
val messages = TellManager.load(testFile.toAbsolutePath().toString())
for (i in messages.indices) {
assertThat(messages).index(i).all {
prop(TellMessage::sender).isEqualTo(testMessages[i].sender)
prop(TellMessage::recipient).isEqualTo(testMessages[i].recipient)
prop(TellMessage::message).isEqualTo(testMessages[i].message)
}
}
}
}

View file

@ -0,0 +1,91 @@
/*
* EntriesUtilsTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.entries
import assertk.assertThat
import assertk.assertions.contains
import assertk.assertions.isEqualTo
import net.thauvin.erik.mobibot.Constants
import net.thauvin.erik.mobibot.entries.EntriesUtils.printComment
import net.thauvin.erik.mobibot.entries.EntriesUtils.printLink
import net.thauvin.erik.mobibot.entries.EntriesUtils.printTags
import net.thauvin.erik.mobibot.entries.EntriesUtils.toLinkLabel
import kotlin.test.Test
class EntriesUtilsTest {
private val comment = EntryComment("comment", "nick")
private val links = buildList {
for (i in 0..5) {
add(
EntryLink(
"https://www.mobitopia.org/$i",
"Mobitopia$i",
"Skynx$i",
"JimH$i",
"#mobitopia$i",
listOf("tag1", "tag2", "tag3", "TAG4", "Tag5")
)
)
}
}
@Test
fun printCommentTest() {
assertThat(printComment(0, 0, comment)).isEqualTo("${Constants.LINK_CMD}1.1: [nick] comment")
}
@Test
fun printLinkTest() {
for (i in links.indices) {
assertThat(
printLink(i - 1, links[i]), "link $i"
).isEqualTo("L$i: [Skynx$i] \u0002Mobitopia$i\u0002 ( \u000303https://www.mobitopia.org/$i\u000F )")
}
assertThat(links.first().addComment(comment), "addComment()").isEqualTo(0)
assertThat(printLink(0, links.first(), isView = true), "printLink(isView=true)").contains("[+1]")
}
@Test
fun printTagsTest() {
for (i in links.indices) {
assertThat(
printTags(i - 1, links[i]), "tag $i"
).isEqualTo("L${i}T: tag1, tag2, tag3, tag4, tag5")
}
}
@Test
fun toLinkLabelTest() {
assertThat(1.toLinkLabel()).isEqualTo("${Constants.LINK_CMD}2")
}
}

View file

@ -0,0 +1,133 @@
/*
* EntryLinkTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.entries
import assertk.all
import assertk.assertThat
import assertk.assertions.*
import com.rometools.rome.feed.synd.SyndCategory
import com.rometools.rome.feed.synd.SyndCategoryImpl
import kotlin.test.Test
import java.security.SecureRandom
import java.util.*
/**
* The `EntryUtilsTest` class.
*
* @author [Erik C. Thauvin](https://erik.thauvin.net/)
* @created 2019-04-19
* @since 1.0
*/
class EntryLinkTest {
private val entryLink = EntryLink(
"https://www.mobitopia.org/", "Mobitopia", "Skynx", "JimH", "#mobitopia",
listOf("tag1", "tag2", "tag3", "TAG4", "Tag5")
)
@Test
fun testAddDeleteComment() {
var i = 0
while (i < 5) {
entryLink.addComment("c$i", "u$i")
i++
}
assertThat(entryLink.comments, "comments").size().isEqualTo(i)
i = 0
for (comment in entryLink.comments) {
assertThat(comment).all {
prop(EntryComment::comment).isEqualTo("c$i")
prop(EntryComment::nick).isEqualTo("u$i")
}
i++
}
val r = SecureRandom()
while (entryLink.comments.size > 0) {
entryLink.deleteComment(r.nextInt(entryLink.comments.size))
}
assertThat(entryLink.comments, "hasComments()").isEmpty()
entryLink.addComment("nothing", "nobody")
entryLink.setComment(0, "something", "somebody")
val comment = entryLink.getComment(0)
assertThat(comment, "comment[first]").all {
prop(EntryComment::nick).isEqualTo("somebody")
prop(EntryComment::comment).isEqualTo("something")
}
assertThat(entryLink.deleteComment(comment), "deleteComment").isTrue()
assertThat(entryLink.deleteComment(comment), "comment is already deleted").isFalse()
}
@Test
fun testConstructor() {
val tags = listOf(SyndCategoryImpl().apply { name = "tag1" }, SyndCategoryImpl().apply { name = "tag2" })
val link = EntryLink("link", "title", "nick", "channel", Date(), tags)
assertThat(link, "link").all {
prop(EntryLink::tags).size().isEqualTo(tags.size)
prop(EntryLink::tags).index(0).prop(SyndCategory::getName).isEqualTo("tag1")
}
}
@Test
fun testMatches() {
assertThat(entryLink.matches("mobitopia"), "matches(mobitopia)").isTrue()
assertThat(entryLink.matches("skynx"), "match(nick)").isTrue()
assertThat(entryLink.matches("www.mobitopia.org"), "matches(url)").isTrue()
assertThat(entryLink.matches("foo"), "matches(foo)").isFalse()
assertThat(entryLink.matches("<empty>"), "matches(empty)").isFalse()
assertThat(entryLink.matches(null), "matches(null)").isFalse()
}
@Test
fun testTags() {
val tags: List<SyndCategory> = entryLink.tags
for ((i, tag) in tags.withIndex()) {
assertThat(tag.name, "tag.name($i)").isEqualTo("tag${i + 1}")
}
assertThat(entryLink::tags).size().isEqualTo(5)
entryLink.setTags("-tag5, tag4")
entryLink.setTags("+mobitopia")
entryLink.setTags("-mobitopia")
assertThat(
entryLink.formatTags(","),
"formatTags(',')"
).isEqualTo("tag1,tag2,tag3,tag4,mobitopia")
entryLink.setTags("-tag4 tag5")
assertThat(
entryLink.formatTags(" ", ","), "formatTag(' ',',')"
).isEqualTo(",tag1 tag2 tag3 mobitopia tag5")
val size = entryLink.tags.size
entryLink.setTags("")
assertThat(entryLink.tags, "setTags('')").size().isEqualTo(size)
entryLink.setTags(" ")
assertThat(entryLink.tags, "setTags(' ')").size().isEqualTo(size)
}
}

View file

@ -0,0 +1,115 @@
/*
* FeedMgrTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.entries
import assertk.all
import assertk.assertThat
import assertk.assertions.*
import net.thauvin.erik.mobibot.Utils.today
import org.testng.annotations.BeforeSuite
import kotlin.test.Test
import java.nio.file.Paths
import java.util.*
import kotlin.io.path.deleteIfExists
import kotlin.io.path.fileSize
import kotlin.io.path.name
class FeedMgrTest {
private val entries = Entries()
private val channel = "mobibot"
@BeforeSuite(alwaysRun = true)
fun beforeSuite() {
entries.logsDir = "src/test/resources/"
entries.ircServer = "irc.example.com"
entries.channel = channel
entries.backlogs = "https://www.mobitopia.org/mobibot/logs"
}
@Test
fun testFeedMgr() {
// Load the feed
assertThat(FeedsManager.loadFeed(entries), "loadFeed()").isEqualTo("2021-10-31")
assertThat(entries.links, "entries.links").size().isEqualTo(2)
entries.links.forEachIndexed { i, entryLink ->
assertThat(entryLink, "entryLink[${i + 1}]").all {
prop(EntryLink::title).isEqualTo("Example ${i + 1}")
prop(EntryLink::link).isEqualTo("https://www.example.com/${i + 1}")
prop(EntryLink::channel).isEqualTo(channel)
}
entryLink.tags.forEachIndexed { y, tag ->
assertThat(tag.name, "tag${i + 1}-${y + 1}").isEqualTo("tag${i + 1}-${y + 1}")
}
}
with(entries.links.first()) {
assertThat(nick, "nick[first]").isEqualTo("ErikT")
assertThat(date, "date[first]").isEqualTo(Date(1635638400000L))
assertThat(comments.first(), "comments[first]").all {
prop(EntryComment::comment).endsWith("comment 1.")
prop(EntryComment::nick).isEqualTo("ErikT")
}
assertThat(comments.last(), "comments[last]").all {
prop(EntryComment::comment).endsWith("comment 2.")
prop(EntryComment::nick).isEqualTo("Skynx")
}
}
assertThat(entries.links, "links").index(1).all {
prop(EntryLink::nick).isEqualTo("Skynx")
prop(EntryLink::date).isEqualTo(Date(1635638460000L))
}
val currentFile = Paths.get("${entries.logsDir}test.xml")
val backlogFile = Paths.get("${entries.logsDir}${today()}.xml")
// Save the feed
FeedsManager.saveFeed(entries, currentFile.name)
assertThat(currentFile, "currentFile").exists()
assertThat(backlogFile, "backlogFile").exists()
assertThat(currentFile.fileSize(), "currentFile == backlogFile").isEqualTo(backlogFile.fileSize())
// Load the test feed
entries.links.clear()
FeedsManager.loadFeed(entries, currentFile.name)
entries.links.forEachIndexed { i, entryLink ->
assertThat(entryLink.title, "entryLink.title[${i + 1}]").isEqualTo("Example ${i + 1}")
}
assertThat(currentFile.deleteIfExists(), "currentFile.deleteIfExists()").isTrue()
assertThat(backlogFile.deleteIfExists(), "backlogFile.deleteIfExists()").isTrue()
}
}

View file

@ -0,0 +1,53 @@
/*
* CalcTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.modules
import assertk.assertFailure
import assertk.assertThat
import assertk.assertions.isEqualTo
import assertk.assertions.isInstanceOf
import net.objecthunter.exp4j.tokenizer.UnknownFunctionOrVariableException
import net.thauvin.erik.mobibot.Utils.bold
import net.thauvin.erik.mobibot.modules.Calc.Companion.calculate
import kotlin.test.Test
/**
* The `CalcTest` class.
*/
class CalcTest {
@Test
fun testCalculate() {
assertThat(calculate("1 + 1"), "calculate(1+1)").isEqualTo("1+1 = ${2.bold()}")
assertThat(calculate("1 -3"), "calculate(1-3)").isEqualTo("1-3 = ${(-2).bold()}")
assertThat(calculate("pi+π+e+φ"), "calculate(pi+π+e+φ)").isEqualTo("pi+π+e+φ = ${"10.62".bold()}")
assertFailure { calculate("one + one") }.isInstanceOf(UnknownFunctionOrVariableException::class.java)
}
}

View file

@ -0,0 +1,62 @@
/*
* ChatGptTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.modules
import assertk.assertFailure
import assertk.assertThat
import assertk.assertions.contains
import assertk.assertions.hasNoCause
import assertk.assertions.isInstanceOf
import net.thauvin.erik.mobibot.LocalProperties
import kotlin.test.Test
class ChatGptTest : LocalProperties() {
@Test
fun testApiKey() {
assertFailure { ChatGpt.chat("1 gallon to liter", "", 0) }
.isInstanceOf(ModuleException::class.java)
.hasNoCause()
}
@Test(groups = ["modules", "no-ci"])
fun testChat() {
val apiKey = getProperty(ChatGpt.API_KEY_PROP)
assertThat(
ChatGpt.chat("how do I make an HTTP request in Javascript?", apiKey, 100)
).contains("XMLHttpRequest")
assertThat(
ChatGpt.chat("how do I encode a URL in java?", apiKey, 60)
).contains("URLEncoder")
assertFailure { ChatGpt.chat("1 liter to gallon", apiKey, 0) }
.isInstanceOf(ModuleException::class.java)
}
}

View file

@ -0,0 +1,78 @@
/*
* CryptoPricesTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.modules
import assertk.all
import assertk.assertThat
import assertk.assertions.isEqualTo
import assertk.assertions.isGreaterThan
import assertk.assertions.prop
import net.thauvin.erik.crypto.CryptoPrice
import net.thauvin.erik.mobibot.modules.CryptoPrices.Companion.currentPrice
import net.thauvin.erik.mobibot.modules.CryptoPrices.Companion.getCurrencyName
import net.thauvin.erik.mobibot.modules.CryptoPrices.Companion.loadCurrencies
import org.testng.annotations.BeforeClass
import kotlin.test.Test
/**
* The `CryptoPricesTest` class.
*/
class CryptoPricesTest {
@BeforeClass
@Throws(ModuleException::class)
fun before() {
loadCurrencies()
}
@Test
@Throws(ModuleException::class)
fun testMarketPrice() {
var price = currentPrice(listOf("BTC"))
assertThat(price, "currentPrice(BTC)").all {
prop(CryptoPrice::base).isEqualTo("BTC")
prop(CryptoPrice::currency).isEqualTo("USD")
prop(CryptoPrice::amount).transform { it.signum() }.isGreaterThan(0)
}
price = currentPrice(listOf("ETH", "EUR"))
assertThat(price, "currentPrice(ETH, EUR)").all {
prop(CryptoPrice::base).isEqualTo("ETH")
prop(CryptoPrice::currency).isEqualTo("EUR")
prop(CryptoPrice::amount).transform { it.signum() }.isGreaterThan(0)
}
}
@Test
fun testGetCurrencyName() {
assertThat(getCurrencyName("USD"), "USD").isEqualTo("United States Dollar")
assertThat(getCurrencyName("EUR"), "EUR").isEqualTo("Euro")
}
}

View file

@ -0,0 +1,85 @@
/*
* CurrencyConverterTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.modules
import assertk.all
import assertk.assertThat
import assertk.assertions.contains
import assertk.assertions.isInstanceOf
import assertk.assertions.matches
import assertk.assertions.prop
import net.thauvin.erik.mobibot.LocalProperties
import net.thauvin.erik.mobibot.modules.CurrencyConverter.Companion.convertCurrency
import net.thauvin.erik.mobibot.modules.CurrencyConverter.Companion.loadSymbols
import net.thauvin.erik.mobibot.msg.ErrorMessage
import net.thauvin.erik.mobibot.msg.Message
import net.thauvin.erik.mobibot.msg.PublicMessage
import org.testng.annotations.BeforeClass
import kotlin.test.Test
/**
* The `CurrencyConvertTest` class.
*/
class CurrencyConverterTest : LocalProperties() {
@BeforeClass
@Throws(ModuleException::class)
fun before() {
val apiKey = getProperty(CurrencyConverter.API_KEY_PROP)
loadSymbols(apiKey)
}
@Test
fun testConvertCurrency() {
val apiKey = getProperty(CurrencyConverter.API_KEY_PROP)
assertThat(
convertCurrency(apiKey, "100 USD to EUR").msg,
"convertCurrency(100 USD to EUR)"
).matches("100 United States Dollar = \\d{2,3}\\.\\d{2,3} Euro".toRegex())
assertThat(
convertCurrency(apiKey, "1 USD to GBP").msg,
"convertCurrency(1 USD to BGP)"
).matches("1 United States Dollar = 0\\.\\d{2,3} Pound Sterling".toRegex())
assertThat(
convertCurrency(apiKey, "100,000.00 CAD to USD").msg,
"convertCurrency(100,000.00 GBP to USD)"
).matches("100,000.00 Canadian Dollar = \\d+\\.\\d{2,3} United States Dollar".toRegex())
assertThat(convertCurrency(apiKey, "100 USD to USD"), "convertCurrency(100 USD to USD)").all {
prop(Message::msg).contains("You're kidding, right?")
isInstanceOf(PublicMessage::class.java)
}
assertThat(convertCurrency(apiKey, "100 USD"), "convertCurrency(100 USD)").all {
prop(Message::msg).contains("Invalid query.")
isInstanceOf(ErrorMessage::class.java)
}
}
}

View file

@ -0,0 +1,53 @@
/*
* DiceTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.modules
import assertk.assertThat
import assertk.assertions.isEqualTo
import assertk.assertions.matches
import kotlin.test.Test
class DiceTest {
@Test
fun testRoll() {
assertThat(Dice.roll(1, 1), "roll(1d1)").isEqualTo("\u00021\u0002")
assertThat(Dice.roll(2, 1), "roll(2d1)")
.isEqualTo("\u00021\u0002 + \u00021\u0002 = \u00022\u0002")
assertThat(Dice.roll(5, 1), "roll(5d1)")
.isEqualTo("\u00021\u0002 + \u00021\u0002 + \u00021\u0002 + \u00021\u0002 + \u00021\u0002 = \u00025\u0002")
assertThat(Dice.roll(2, 6), "roll(2d6)")
.matches("\u0002[1-6]\u0002 \\+ \u0002[1-6]\u0002 = \u0002[1-9][0-2]?\u0002".toRegex())
assertThat(Dice.roll(3, 7), "roll(3d7)")
.matches("\u0002[1-7]\u0002 \\+ \u0002[1-7]\u0002 \\+ \u0002[1-7]\u0002 = \u0002\\d{1,2}\u0002".toRegex())
}
}

View file

@ -0,0 +1,95 @@
/*
* GoogleSearchTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.modules
import assertk.all
import assertk.assertFailure
import assertk.assertThat
import assertk.assertions.*
import net.thauvin.erik.mobibot.ExceptionSanitizer.sanitize
import net.thauvin.erik.mobibot.LocalProperties
import net.thauvin.erik.mobibot.modules.GoogleSearch.Companion.searchGoogle
import net.thauvin.erik.mobibot.msg.ErrorMessage
import net.thauvin.erik.mobibot.msg.Message
import kotlin.test.Test
/**
* The `GoogleSearchTest` class.
*/
class GoogleSearchTest : LocalProperties() {
@Test
fun testAPIKeys() {
assertThat(
searchGoogle("", "apikey", "cssKey").first(),
"searchGoogle(empty)"
).isInstanceOf(ErrorMessage::class.java)
assertFailure { searchGoogle("test", "", "apiKey") }
.isInstanceOf(ModuleException::class.java).hasNoCause()
assertFailure { searchGoogle("test", "apiKey", "") }
.isInstanceOf(ModuleException::class.java).hasNoCause()
assertFailure { searchGoogle("test", "apiKey", "cssKey") }
.isInstanceOf(ModuleException::class.java)
.hasMessage("API key not valid. Please pass a valid API key.")
}
@Test\n@DisableOnCi
@Throws(ModuleException::class)
fun testSearchGoogle() {
val apiKey = getProperty(GoogleSearch.API_KEY_PROP)
val cseKey = getProperty(GoogleSearch.CSE_KEY_PROP)
try {
var query = "mobibot"
var messages = searchGoogle(query, apiKey, cseKey)
assertThat(messages, "searchGoogle($query)").all {
isNotEmpty()
index(0).prop(Message::msg).contains(query, true)
}
query = "adadflkjl"
messages = searchGoogle(query, apiKey, cseKey)
assertThat(messages, "searchGoogle($query)").index(0).all {
isInstanceOf(ErrorMessage::class.java)
prop(Message::msg).isEqualTo("No results found.")
}
} catch (e: ModuleException) {
// Avoid displaying api keys in CI logs
if ("true" == System.getenv("CI")) {
throw e.sanitize(apiKey, cseKey)
} else {
throw e
}
}
}
}

View file

@ -0,0 +1,57 @@
/*
* JokeTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.modules
import assertk.all
import assertk.assertThat
import assertk.assertions.*
import net.thauvin.erik.mobibot.modules.Joke.Companion.randomJoke
import net.thauvin.erik.mobibot.msg.Message
import net.thauvin.erik.mobibot.msg.PublicMessage
import kotlin.test.Test
/**
* The `JokeTest` class.
*/
class JokeTest {
@Test
@Throws(ModuleException::class)
fun testRandomJoke() {
val joke = randomJoke()
assertThat(joke, "randomJoke()").all {
size().isGreaterThan(0)
each {
it.isInstanceOf(PublicMessage::class.java)
it.prop(Message::msg).doesNotContain("\n")
}
}
}
}

View file

@ -0,0 +1,60 @@
/*
* LookupTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.modules
import assertk.assertThat
import assertk.assertions.any
import assertk.assertions.contains
import net.thauvin.erik.mobibot.modules.Lookup.Companion.nslookup
import net.thauvin.erik.mobibot.modules.Lookup.Companion.whois
import kotlin.test.Test
/**
* The `Lookup Test` class.
*/
class LookupTest {
@Test
@Throws(Exception::class)
fun testLookup() {
var result = nslookup("apple.com")
assertThat(result, "lookup(apple.com)").contains("17.253.144.10")
result = nslookup("204.122.16.136")
assertThat(result, "lookup(204.122.16.136)").contains("nix3.thauvin.us")
}
@Test
@Throws(Exception::class)
fun testWhois() {
val result = whois("17.178.96.59", Lookup.WHOIS_HOST)
assertThat(result, "whois(17.178.96.59").any { it.contains("Apple Inc.") }
}
}

View file

@ -0,0 +1,54 @@
/*
* MastodonTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.modules
import assertk.assertThat
import assertk.assertions.contains
import net.thauvin.erik.mobibot.LocalProperties
import net.thauvin.erik.mobibot.modules.Mastodon.Companion.toot
import kotlin.test.Test
class MastodonTest : LocalProperties() {
@Test
@Throws(ModuleException::class)
fun testToot() {
val msg = "Testing Mastodon API from ${getHostName()}"
assertThat(
toot(
getProperty(Mastodon.ACCESS_TOKEN_PROP),
getProperty(Mastodon.INSTANCE_PROP),
getProperty(Mastodon.HANDLE_PROP),
msg,
true
)
).contains(msg)
}
}

View file

@ -0,0 +1,105 @@
/*
* ModuleExceptionTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.modules
import assertk.all
import assertk.assertThat
import assertk.assertions.*
import net.thauvin.erik.mobibot.ExceptionSanitizer.sanitize
import org.testng.annotations.DataProvider
import kotlin.test.Test
import java.io.IOException
import java.lang.reflect.Method
/**
* The `ModuleExceptionTest` class.
*/
class ModuleExceptionTest {
companion object {
const val DEBUG_MESSAGE = "debugMessage"
const val MESSAGE = "message"
}
@DataProvider(name = "dp")
fun createData(@Suppress("UNUSED_PARAMETER") m: Method?): Array<Array<Any>> {
return arrayOf(
arrayOf(ModuleException(DEBUG_MESSAGE, MESSAGE, IOException("URL http://foobar.com"))),
arrayOf(ModuleException(DEBUG_MESSAGE, MESSAGE, IOException("URL http://foobar.com?"))),
arrayOf(ModuleException(DEBUG_MESSAGE, MESSAGE))
)
}
@Test(dataProvider = "dp")
fun testGetDebugMessage(e: ModuleException) {
assertThat(e::debugMessage).isEqualTo(DEBUG_MESSAGE)
}
@Test(dataProvider = "dp")
fun testGetMessage(e: ModuleException) {
assertThat(e).hasMessage(MESSAGE)
}
@Test
fun testSanitizeMessage() {
val apiKey = "1234567890"
var e = ModuleException(DEBUG_MESSAGE, MESSAGE, IOException("URL http://foo.com?apiKey=$apiKey&userID=me"))
assertThat(
e.sanitize(apiKey, "", "me").message, "ModuleException(debugMessage, message, IOException(url))"
).isNotNull().all {
contains("xxxxxxxxxx", "userID=xx", "java.io.IOException")
doesNotContain(apiKey, "me")
}
e = ModuleException(DEBUG_MESSAGE, MESSAGE, null)
assertThat(e.sanitize(apiKey), "ModuleException(debugMessage, message, null)").hasMessage(MESSAGE)
e = ModuleException(DEBUG_MESSAGE, MESSAGE, IOException())
assertThat(e.sanitize(apiKey), "ModuleException(debugMessage, message, IOException())").hasMessage(MESSAGE)
e = ModuleException(DEBUG_MESSAGE, apiKey)
assertThat(e.sanitize(apiKey).message, "ModuleException(debugMessage, apiKey)").isNotNull()
.doesNotContain(apiKey)
val msg: String? = null
e = ModuleException(DEBUG_MESSAGE, msg, IOException(msg))
assertThat(e.sanitize(apiKey).message, "ModuleException(debugMessage, msg, IOException(msg))").isNull()
e = ModuleException(DEBUG_MESSAGE, msg, IOException("foo is $apiKey"))
assertThat(
e.sanitize(" ", apiKey, "foo").message,
"ModuleException(debugMessage, msg, IOException(foo is $apiKey))"
).isNotNull().all {
doesNotContain(apiKey)
endsWith("xxx is xxxxxxxxxx")
}
assertThat(e.sanitize(), "exception should be unchanged").isEqualTo(e)
}
}

View file

@ -0,0 +1,54 @@
/*
* PingTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.modules
import assertk.assertThat
import assertk.assertions.contains
import assertk.assertions.isNotEmpty
import net.thauvin.erik.mobibot.modules.Ping.Companion.randomPing
import kotlin.test.Test
/**
* The `PingTest` class.
*/
class PingTest {
@Test
fun testPingsArray() {
assertThat(Ping.PINGS, "Ping.PINGS").isNotEmpty()
}
@Test
fun testRandomPing() {
for (i in 0..9) {
assertThat(Ping.PINGS, "Ping.PINGS[$i]").contains(randomPing())
}
}
}

View file

@ -0,0 +1,50 @@
/*
* RockPaperScissorsTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.modules
import assertk.assertThat
import assertk.assertions.isEqualTo
import net.thauvin.erik.mobibot.modules.RockPaperScissors.Companion.winLoseOrDraw
import kotlin.test.Test
class RockPaperScissorsTest {
@Test
fun testWinLoseOrDraw() {
assertThat(winLoseOrDraw("scissors", "paper"), "scissors vs. paper").isEqualTo("win")
assertThat(winLoseOrDraw("paper", "rock"), "paper vs. rock").isEqualTo("win")
assertThat(winLoseOrDraw("rock", "scissors"), "rock vs. scissors").isEqualTo("win")
assertThat(winLoseOrDraw("paper", "scissors"), "paper vs. scissors").isEqualTo("lose")
assertThat(winLoseOrDraw("rock", "paper"), "rock vs. paper").isEqualTo("lose")
assertThat(winLoseOrDraw("scissors", "rock"), "scissors vs. rock").isEqualTo("lose")
assertThat(winLoseOrDraw("scissors", "scissors"), "scissors vs. scissors").isEqualTo("draw")
}
}

View file

@ -0,0 +1,85 @@
/*
* StockQuoteTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.modules
import assertk.all
import assertk.assertFailure
import assertk.assertThat
import assertk.assertions.*
import net.thauvin.erik.mobibot.ExceptionSanitizer.sanitize
import net.thauvin.erik.mobibot.LocalProperties
import net.thauvin.erik.mobibot.modules.StockQuote.Companion.getQuote
import net.thauvin.erik.mobibot.msg.ErrorMessage
import net.thauvin.erik.mobibot.msg.Message
import kotlin.test.Test
/**
* The `StockQuoteTest` class.
*/
class StockQuoteTest : LocalProperties() {
private fun buildMatch(label: String): String {
return "${label}:[ ]+[0-9.]+".prependIndent()
}
@Test
@Throws(ModuleException::class)
fun testGetQuote() {
val apiKey = getProperty(StockQuote.API_KEY_PROP)
try {
var symbol = "apple inc"
val messages = getQuote(symbol, apiKey)
assertThat(messages, "response not empty").isNotEmpty()
assertThat(messages, "getQuote($symbol)").index(0).prop(Message::msg).matches("Symbol: AAPL .*".toRegex())
assertThat(messages, "getQuote($symbol)").index(1).prop(Message::msg).matches(buildMatch("Price").toRegex())
assertThat(messages, "getQuote($symbol)").index(2).prop(Message::msg)
.matches(buildMatch("Previous").toRegex())
assertThat(messages, "getQuote($symbol)").index(3).prop(Message::msg).matches(buildMatch("Open").toRegex())
symbol = "blahfoo"
assertThat(getQuote(symbol, apiKey).first(), "getQuote($symbol)").all {
isInstanceOf(ErrorMessage::class.java)
prop(Message::msg).isEqualTo(StockQuote.INVALID_SYMBOL)
}
assertThat(getQuote("", "apikey").first(), "getQuote(empty)").all {
isInstanceOf(ErrorMessage::class.java)
prop(Message::msg).isEqualTo(StockQuote.INVALID_SYMBOL)
}
assertFailure { getQuote("test", "") }.isInstanceOf(ModuleException::class.java).hasNoCause()
} catch (e: ModuleException) {
// Avoid displaying api keys in CI logs
if ("true" == System.getenv("CI")) {
throw e.sanitize(apiKey)
} else {
throw e
}
}
}
}

View file

@ -0,0 +1,117 @@
/*
* Weather2Test.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.modules
import assertk.all
import assertk.assertFailure
import assertk.assertThat
import assertk.assertions.*
import net.aksingh.owmjapis.api.APIException
import net.aksingh.owmjapis.core.OWM
import net.thauvin.erik.mobibot.LocalProperties
import net.thauvin.erik.mobibot.modules.Weather2.Companion.API_KEY_PROP
import net.thauvin.erik.mobibot.modules.Weather2.Companion.ftoC
import net.thauvin.erik.mobibot.modules.Weather2.Companion.getCountry
import net.thauvin.erik.mobibot.modules.Weather2.Companion.getWeather
import net.thauvin.erik.mobibot.modules.Weather2.Companion.mphToKmh
import net.thauvin.erik.mobibot.msg.Message
import kotlin.test.Test
/**
* The `Weather2Test` class.
*/
class Weather2Test : LocalProperties() {
@Test
fun testFtoC() {
val t = ftoC(32.0)
assertThat(t.second, "32 °F is 0 °C").isEqualTo(0)
}
@Test
fun testGetCountry() {
assertThat(getCountry("foo"), "foo is not a valid country").isEqualTo(OWM.Country.UNITED_STATES)
assertThat(getCountry("fr"), "country should France").isEqualTo(OWM.Country.FRANCE)
val country = OWM.Country.entries.toTypedArray()
repeat(3) {
val rand = country[(country.indices).random()]
assertThat(getCountry(rand.value), rand.name).isEqualTo(rand)
}
}
@Test
fun testMphToKmh() {
val w = mphToKmh(0.62)
assertThat(w.second, "0.62 mph is 1 km/h").isEqualTo(1)
}
@Test
@Throws(ModuleException::class)
fun testWeather() {
var query = "98204"
var messages = getWeather(query, getProperty(API_KEY_PROP))
assertThat(messages, "getWeather($query)").index(0).prop(Message::msg).all {
contains("Everett, United States")
contains("US")
}
assertThat(messages, "getWeather($query)").index(messages.size - 1).prop(Message::msg).endsWith("98204%2CUS")
query = "San Francisco"
messages = getWeather(query, getProperty(API_KEY_PROP))
assertThat(messages, "getWeather($query)").index(0).prop(Message::msg).all {
contains("San Francisco")
contains("US")
}
assertThat(messages, "getWeather($query)").index(messages.size - 1).prop(Message::msg).endsWith("5391959")
query = "London, GB"
messages = getWeather(query, getProperty(API_KEY_PROP))
assertThat(messages, "getWeather($query)").index(0).prop(Message::msg).all {
contains("London, United Kingdom")
contains("GB")
}
assertThat(messages, "getWeather($query)").index(messages.size - 1).prop(Message::msg).endsWith("2643743")
try {
query = "Foo, US"
getWeather(query, getProperty(API_KEY_PROP))
} catch (e: ModuleException) {
assertThat(e.cause, "getWeather($query)").isNotNull().isInstanceOf(APIException::class.java)
}
query = "test"
assertFailure { getWeather(query, "") }.isInstanceOf(ModuleException::class.java).hasNoCause()
assertFailure { getWeather(query, null) }.isInstanceOf(ModuleException::class.java).hasNoCause()
messages = getWeather("", "apikey")
assertThat(messages, "getWeather(empty)").index(0).prop(Message::isError).isTrue()
}
}

View file

@ -0,0 +1,77 @@
/*
* WolframAlphaTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.modules
import assertk.assertFailure
import assertk.assertThat
import assertk.assertions.contains
import assertk.assertions.hasMessage
import assertk.assertions.isInstanceOf
import net.thauvin.erik.mobibot.ExceptionSanitizer.sanitize
import net.thauvin.erik.mobibot.LocalProperties
import net.thauvin.erik.mobibot.modules.WolframAlpha.Companion.queryWolfram
import kotlin.test.Test
class WolframAlphaTest : LocalProperties() {
@Test
fun testAppId() {
assertFailure { queryWolfram("1 gallon to liter", appId = "DEMO") }
.isInstanceOf(ModuleException::class.java)
.hasMessage("Error 1: Invalid appid")
assertFailure { queryWolfram("1 gallon to liter", appId = "") }
.isInstanceOf(ModuleException::class.java)
}
@Test(groups = ["modules", "no-ci"])
@Throws(ModuleException::class)
fun queryWolframTest() {
val apiKey = getProperty(WolframAlpha.APPID_KEY_PROP)
try {
var query = "SFO to SEA"
assertThat(queryWolfram(query, appId = apiKey), "queryWolfram($query)").contains("miles")
query = "SFO to LAX"
assertThat(
queryWolfram(query, WolframAlpha.METRIC, apiKey),
"queryWolfram($query)"
).contains("kilometers")
} catch (e: ModuleException) {
// Avoid displaying api key in CI logs
if ("true" == System.getenv("CI")) {
throw e.sanitize(apiKey)
} else {
throw e
}
}
}
}

View file

@ -0,0 +1,70 @@
/*
* WordTimeTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.modules
import assertk.assertThat
import assertk.assertions.endsWith
import assertk.assertions.matches
import assertk.assertions.startsWith
import net.thauvin.erik.mobibot.Utils.bold
import net.thauvin.erik.mobibot.modules.WorldTime.Companion.BEATS_KEYWORD
import net.thauvin.erik.mobibot.modules.WorldTime.Companion.COUNTRIES_MAP
import net.thauvin.erik.mobibot.modules.WorldTime.Companion.time
import org.pircbotx.Colors
import kotlin.test.Test
import java.time.ZoneId
/**
* The `WordTimeTest` class.
*/
class WordTimeTest {
@Test
fun testTime() {
assertThat(time(), "time()").matches(
("The time is ${Colors.BOLD}\\d{1,2}:\\d{2}${Colors.BOLD} " +
"on ${Colors.BOLD}\\w+, \\d{1,2} \\w+ \\d{4}${Colors.BOLD} " +
"in ${Colors.BOLD}Los Angeles${Colors.BOLD}").toRegex()
)
assertThat(time(""), "time()").endsWith("Los Angeles".bold())
assertThat(time("PST"), "time(PST)").endsWith("Los Angeles".bold())
assertThat(time("GB"), "time(GB)").endsWith("London".bold())
assertThat(time("FR"), "time(FR)").endsWith("Paris".bold())
assertThat(time("BLAH"), "time(BLAH)").startsWith("Unsupported")
assertThat(time("BEAT"), "time($BEATS_KEYWORD)").matches("[\\w ]+ .?@\\d{3}+.? .beats".toRegex())
}
@Test
fun testZones() {
COUNTRIES_MAP.filter { it.value != BEATS_KEYWORD }.forEach {
assertThat(ZoneId.of(it.value))
}
}
}

View file

@ -0,0 +1,109 @@
/*
* MessageTest.kt
*
* Copyright 2004-2023 Erik C. Thauvin (erik@thauvin.net)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of this project nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot.msg
import assertk.all
import assertk.assertThat
import assertk.assertions.isFalse
import assertk.assertions.isTrue
import assertk.assertions.prop
import kotlin.test.Test
class MessageTest {
@Test
fun testConstructor() {
var msg = Message("foo")
msg.isError = true
assertThat(msg.isNotice, "message is notice").isTrue()
msg = Message("foo", isError = true)
assertThat(msg.isNotice, "message is notice too").isTrue()
}
@Test
fun testErrorMessage() {
val msg = ErrorMessage("foo")
assertThat(msg).all {
prop(Message::isError).isTrue()
prop(Message::isNotice).isTrue()
prop(Message::isPrivate).isFalse()
}
}
@Test
fun testIsError() {
val msg = Message("foo")
msg.isError = true
assertThat(msg).all {
prop(Message::isError).isTrue()
prop(Message::isNotice).isTrue()
prop(Message::isPrivate).isFalse()
}
msg.isError = false
assertThat(msg).all {
prop(Message::isError).isFalse()
prop(Message::isNotice).isTrue()
prop(Message::isPrivate).isFalse()
}
}
@Test
fun testNoticeMessage() {
val msg = NoticeMessage("food")
assertThat(msg).all {
prop(Message::isError).isFalse()
prop(Message::isNotice).isTrue()
prop(Message::isPrivate).isFalse()
}
}
@Test
fun testPrivateMessage() {
val msg = PrivateMessage("foo")
assertThat(msg).all {
prop(Message::isPrivate).isTrue()
prop(Message::isError).isFalse()
prop(Message::isNotice).isFalse()
}
}
@Test
fun testPublicMessage() {
val msg = PublicMessage("foo")
assertThat(msg).all {
prop(Message::isError).isFalse()
prop(Message::isNotice).isFalse()
prop(Message::isPrivate).isFalse()
}
}
}