Added tests.

This commit is contained in:
Erik C. Thauvin 2017-04-19 02:18:02 -07:00
parent c71713679f
commit d78393e0a5
5 changed files with 419 additions and 140 deletions

View file

@ -8,7 +8,7 @@ import net.thauvin.erik.kobalt.plugin.propertyfile.*
val bs = buildScript { val bs = buildScript {
plugins(file("../kobaltBuild/libs/kobalt-property-file-0.9.0.jar")) plugins(file("../kobaltBuild/libs/kobalt-property-file-0.9.0.jar"))
// plugins("net.thauvin.erik:kobalt-property-file:") //plugins("net.thauvin.erik:kobalt-property-file:")
} }
val p = project { val p = project {
@ -37,7 +37,9 @@ val p = project {
// parameters // parameters
file = "version.properties" file = "version.properties"
comment = "##Generated file - do not modify!" comment = "##Generated file - do not modify!"
// failOnWarning = true
//failOnWarning = true
//entry(key = "version.fail", value = "a", type = Types.INT)
// Version properties with patch increment // Version properties with patch increment
entry(key = "version.major", value = "1") entry(key = "version.major", value = "1")
@ -51,7 +53,7 @@ val p = project {
entry(key = "date.nextMonth", value = "now", type = Types.DATE) entry(key = "date.nextMonth", value = "now", type = Types.DATE)
entry(key = "date.nextMonth", value = "0", type = Types.DATE, unit = Units.MONTH, operation = Operations.ADD) entry(key = "date.nextMonth", value = "0", type = Types.DATE, unit = Units.MONTH, operation = Operations.ADD)
// examples from: https://ant.apache.org/manual/Tasks/propertyfile.html // Examples from: https://ant.apache.org/manual/Tasks/propertyfile.html
entry(key = "akey", value = "avalue") entry(key = "akey", value = "avalue")
entry(key = "adate", type = Types.DATE, value = "now") entry(key = "adate", type = Types.DATE, value = "now")
entry(key = "anint", type = Types.INT, default = "0", operation = Operations.ADD) entry(key = "anint", type = Types.INT, default = "0", operation = Operations.ADD)

View file

@ -44,7 +44,7 @@ val p = project {
} }
dependenciesTest { dependenciesTest {
//compile("org.testng:testng:6.11") compile("org.testng:testng:6.11")
} }
assemble { assemble {

View file

@ -43,23 +43,12 @@ import com.google.inject.Singleton
import java.io.FileOutputStream import java.io.FileOutputStream
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Paths import java.nio.file.Paths
import java.text.*
import java.util.* import java.util.*
@Singleton @Singleton
class PropertyFilePlugin @Inject constructor(val configActor: ConfigActor<PropertyFileConfig>, class PropertyFilePlugin @Inject constructor(val configActor: ConfigActor<PropertyFileConfig>,
val taskContributor: TaskContributor) : val taskContributor: TaskContributor) :
BasePlugin(), ITaskContributor, IConfigActor<PropertyFileConfig> by configActor { BasePlugin(), ITaskContributor, IConfigActor<PropertyFileConfig> by configActor {
private val calendarFields = mapOf(
Units.MILLISECOND to Calendar.MILLISECOND,
Units.SECOND to Calendar.SECOND,
Units.MINUTE to Calendar.MINUTE,
Units.HOUR to Calendar.HOUR_OF_DAY,
Units.DAY to Calendar.DATE,
Units.WEEK to Calendar.WEEK_OF_YEAR,
Units.MONTH to Calendar.MONTH,
Units.YEAR to Calendar.YEAR
)
// ITaskContributor // ITaskContributor
override fun tasksFor(project: Project, context: KobaltContext): List<DynamicTask> { override fun tasksFor(project: Project, context: KobaltContext): List<DynamicTask> {
@ -114,9 +103,9 @@ class PropertyFilePlugin @Inject constructor(val configActor: ConfigActor<Proper
p.remove(entry.key) p.remove(entry.key)
} else { } else {
when (type) { when (type) {
Types.DATE -> success = processDate(p, entry) Types.DATE -> success = Utils.processDate(p, entry)
Types.INT -> success = processInt(p, entry) Types.INT -> success = Utils.processInt(p, entry)
else -> success = processString(p, entry) else -> success = Utils.processString(p, entry)
} }
} }
} }
@ -136,127 +125,6 @@ class PropertyFilePlugin @Inject constructor(val configActor: ConfigActor<Proper
return TaskResult() return TaskResult()
} }
private fun processDate(p: Properties, entry: Entry): Boolean {
var success = true
val cal = Calendar.getInstance()
val value = currentValue(p.getProperty(entry.key), entry.value, entry.default, entry.operation)
val fmt = SimpleDateFormat(if (entry.pattern.isBlank()) "yyyy-MM-dd HH:mm" else entry.pattern)
if (value.equals("now", true) || value.isBlank()) {
cal.time = Date()
} else {
try {
cal.time = fmt.parse(value)
} catch (pe: ParseException) {
warn("Date parse exception for: ${entry.key}", pe)
success = false
}
}
if (entry.operation != Operations.SET) {
var offset = 0
try {
offset = entry.value!!.toInt()
if (entry.operation == Operations.SUBTRACT) {
offset *= -1
}
} catch (nfe: NumberFormatException) {
warn("Non-integer value for: ${entry.key}")
success = false
}
cal.add(calendarFields.getOrDefault(entry.unit, Calendar.DATE), offset)
}
p.setProperty(entry.key, fmt.format(cal.time))
return success
}
private fun processInt(p: Properties, entry: Entry): Boolean {
var success = true
var intValue: Int
try {
val fmt = DecimalFormat(entry.pattern)
val value = currentValue(p.getProperty(entry.key), entry.value, entry.default, entry.operation)
intValue = fmt.parse(if (value.isBlank()) "0" else value).toInt()
if (entry.operation != Operations.SET) {
var opValue = 1
if (entry.value != null) {
opValue = fmt.parse(entry.value).toInt()
}
if (entry.operation == Operations.ADD) {
intValue += opValue
} else if (entry.operation == Operations.SUBTRACT) {
intValue -= opValue
}
}
p.setProperty(entry.key, fmt.format(intValue))
} catch (nfe: NumberFormatException) {
warn("Number format exception for: ${entry.key}", nfe)
success = false
} catch (pe: ParseException) {
warn("Number parsing exception for: ${entry.key}", pe)
success = false
}
return success
}
private fun processString(p: Properties, entry: Entry): Boolean {
val value = currentValue(p.getProperty(entry.key), entry.value, entry.default, entry.operation)
if (entry.operation == Operations.SET) {
p.setProperty(entry.key, value)
} else if (entry.operation == Operations.ADD) {
if (entry.value != null) {
p.setProperty(entry.key, "$value${entry.value}")
}
}
return true
}
private fun currentValue(value: String?, newValue: String?, default: String?, operation: Operations): String {
var result: String? = null
if (operation == Operations.SET) {
if (newValue != null && default == null) {
result = newValue
}
if (default != null) {
if (newValue == null && value != null) {
result = value
}
if (newValue == null && value == null) {
result = default
}
if (newValue != null && value != null) {
result = newValue
}
if (newValue != null && value == null) {
result = default
}
}
} else {
result = value ?: default
}
if (result == null) {
result = ""
}
return result
}
} }
enum class Types { enum class Types {
@ -296,7 +164,7 @@ class PropertyFileConfig {
operation: Operations = Operations.SET, operation: Operations = Operations.SET,
pattern: String = "", pattern: String = "",
unit: Units = Units.DAY) { unit: Units = Units.DAY) {
if (key.isNotEmpty()) entries.add(Entry(key, value, default, type, operation, pattern, unit)) entries.add(Entry(key, value, default, type, operation, pattern, unit))
} }
} }

View file

@ -0,0 +1,179 @@
/*
* Utils.kt
*
* Copyright (c) 2017, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved.
*
* 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.kobalt.plugin.propertyfile
import com.beust.kobalt.misc.warn
import java.text.*
import java.util.*
/**
* The <code>Utils</code> class.
*
* @author <a href="mailto:erik@thauvin.net" target="_blank">Erik C. Thauvin</a>
* @created 2017-04-18
* @since 1.0
*/
class Utils {
companion object {
private val calendarFields = mapOf(
Units.MILLISECOND to Calendar.MILLISECOND,
Units.SECOND to Calendar.SECOND,
Units.MINUTE to Calendar.MINUTE,
Units.HOUR to Calendar.HOUR_OF_DAY,
Units.DAY to Calendar.DATE,
Units.WEEK to Calendar.WEEK_OF_YEAR,
Units.MONTH to Calendar.MONTH,
Units.YEAR to Calendar.YEAR
)
fun processDate(p: Properties, entry: Entry): Boolean {
var success = true
val cal = Calendar.getInstance()
val value = Utils.currentValue(p.getProperty(entry.key), entry.value, entry.default, entry.operation)
val fmt = SimpleDateFormat(if (entry.pattern.isBlank()) "yyyy-MM-dd HH:mm" else entry.pattern)
if (value.equals("now", true) || value.isBlank()) {
cal.time = Date()
} else {
try {
cal.time = fmt.parse(value)
} catch (pe: ParseException) {
warn("Date parse exception for: ${entry.key}", pe)
success = false
}
}
if (entry.operation != Operations.SET) {
var offset = 0
try {
offset = entry.value!!.toInt()
if (entry.operation == Operations.SUBTRACT) {
offset *= -1
}
} catch (nfe: NumberFormatException) {
warn("Non-integer value for: ${entry.key}")
success = false
}
cal.add(calendarFields.getOrDefault(entry.unit, Calendar.DATE), offset)
}
p.setProperty(entry.key, fmt.format(cal.time))
return success
}
fun processInt(p: Properties, entry: Entry): Boolean {
var success = true
var intValue: Int
try {
val fmt = DecimalFormat(entry.pattern)
val value = Utils.currentValue(p.getProperty(entry.key), entry.value, entry.default, entry.operation)
intValue = fmt.parse(if (value.isBlank()) "0" else value).toInt()
if (entry.operation != Operations.SET) {
var opValue = 1
if (entry.value != null) {
opValue = fmt.parse(entry.value).toInt()
}
if (entry.operation == Operations.ADD) {
intValue += opValue
} else if (entry.operation == Operations.SUBTRACT) {
intValue -= opValue
}
}
p.setProperty(entry.key, fmt.format(intValue))
} catch (nfe: NumberFormatException) {
warn("Number format exception for: ${entry.key}", nfe)
success = false
} catch (pe: ParseException) {
warn("Number parsing exception for: ${entry.key}", pe)
success = false
}
return success
}
fun processString(p: Properties, entry: Entry): Boolean {
val value = Utils.currentValue(p.getProperty(entry.key), entry.value, entry.default, entry.operation)
if (entry.operation == Operations.SET) {
p.setProperty(entry.key, value)
} else if (entry.operation == Operations.ADD) {
if (entry.value != null) {
p.setProperty(entry.key, "$value${entry.value}")
}
}
return true
}
fun currentValue(value: String?, newValue: String?, default: String?, operation: Operations): String {
var result: String? = null
if (operation == Operations.SET) {
if (newValue != null && default == null) {
result = newValue
}
if (default != null) {
if (newValue == null && value != null) {
result = value
}
if (newValue == null && value == null) {
result = default
}
if (newValue != null && value != null) {
result = newValue
}
if (newValue != null && value == null) {
result = default
}
}
} else {
result = value ?: default
}
if (result == null) {
result = ""
}
return result
}
}
}

View file

@ -0,0 +1,230 @@
/*
* UtilsTest.kt
*
* Copyright (c) 2017, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved.
*
* 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.kobalt.plugin.propertyfile
import org.testng.Assert
import org.testng.annotations.Test
import java.text.SimpleDateFormat
import java.util.*
@Test
class UtilsTest {
val p = Properties()
@Test
fun currentValueTest() {
var prev : String?
var value: String?
var default: String? = null
var operation = Operations.SET
// If only value is specified, the property is set to it regardless of its previous value.
prev = "previous"
value = "value"
Assert.assertEquals(Utils.currentValue(prev, value, default, operation), value,
"currentValue($prev,$value,$default,$operation)")
// If only default is specified and the property previously existed, it is unchanged.
prev = "previous"
value = null
default = "default"
Assert.assertEquals(Utils.currentValue(prev, value, default, operation), prev,
"currentValue($prev,$value,$default,$operation)")
// If only default is specified and the property did not exist, the property is set to default.
prev = null
value = null
default = "default"
Assert.assertEquals(Utils.currentValue(prev, value, default, operation), default,
"currentValue($prev,$value,$default,$operation)")
// If value and default are both specified and the property previously existed, the property is set to value.
prev = "previous"
value ="value"
default = "default"
Assert.assertEquals(Utils.currentValue(prev, value, default, operation), value,
"currentValue($prev,$value,$default,$operation)")
// If value and default are both specified and the property did not exist, the property is set to default.
prev = null
value = "value"
default ="default"
Assert.assertEquals(Utils.currentValue(prev, value, default, operation), default,
"currentValue($prev,$value,$default,$operation)")
// ADD
operation = Operations.ADD
prev = null
value = "value"
default = "default"
Assert.assertEquals(Utils.currentValue(prev, value, default, operation), default,
"currentValue($prev,$value,$default,$operation)")
prev = "prev"
value = "value"
default = null
Assert.assertEquals(Utils.currentValue(prev, value, default, operation), prev,
"currentValue($prev,$value,$default,$operation)")
prev = null
value = "value"
default = null
Assert.assertEquals(Utils.currentValue(prev, value, default, operation), "",
"currentValue($prev,$value,$default,$operation)")
prev = null
value = "value"
default = "default"
Assert.assertEquals(Utils.currentValue(prev, value, default, operation), default,
"currentValue($prev,$value,$default,$operation)")
prev = null
value = null
default = null
Assert.assertEquals(Utils.currentValue(prev, value, default, operation), "",
"currentValue($prev,$value,$default,$operation)")
}
@Test
fun processStringTest() {
val entry = Entry()
entry.key = "version.major"
entry.value = "1"
Utils.processString(p, entry)
Assert.assertEquals(entry.value, p.getProperty(entry.key), "processString(${entry.key}, ${entry.value})")
entry.key = "version.minor"
entry.value = "0"
Utils.processString(p, entry)
Assert.assertEquals(entry.value, p.getProperty(entry.key), "processString(${entry.key}, ${entry.value})")
}
@Test
fun processIntTest() {
val entry = Entry()
entry.type = Types.INT
entry.key = "version.patch"
entry.value = "a"
Assert.assertFalse(Utils.processInt(p, entry), "parsetInt(${entry.key}, a)")
// ADD
entry.operation = Operations.ADD
entry.value = "1"
entry.default = "-1"
Utils.processInt(p, entry)
Assert.assertEquals("0", p.getProperty(entry.key), "processInt(${entry.key}, 0)")
entry.key = "anint"
entry.value = null
entry.default = "0"
Utils.processInt(p, entry)
Assert.assertEquals("1", p.getProperty(entry.key), "processInt(${entry.key}, 1)")
Utils.processInt(p, entry)
Assert.assertEquals("2", p.getProperty(entry.key), "processInt(${entry.key}, 2)")
entry.key = "formated.int"
entry.value = null
entry.default = "0013"
entry.pattern = "0000"
Utils.processInt(p, entry)
Assert.assertEquals("0014", p.getProperty(entry.key), "processInt(${entry.key}, 0014)")
Utils.processInt(p, entry)
Assert.assertEquals("0015", p.getProperty(entry.key), "processInt(${entry.key}, 0015)")
entry.key = "formated.int"
entry.value = "2"
entry.default = "0013"
entry.pattern = "0000"
Utils.processInt(p, entry)
Assert.assertEquals("0017", p.getProperty(entry.key), "processInt(${entry.key}, 0017)")
// SUBTRACT
entry.operation = Operations.SUBTRACT
entry.value = null
entry.default = "0013"
entry.pattern = "0000"
Utils.processInt(p, entry)
Assert.assertEquals("0016", p.getProperty(entry.key), "processInt(${entry.key}, 0016)")
}
@Test
fun processDateTest() {
val entry = Entry()
entry.type = Types.DATE
entry.pattern = "D"
entry.key = "adate"
val day = SimpleDateFormat(entry.pattern).format(Date()).toInt()
entry.value = "a"
Assert.assertFalse(Utils.processDate(p, entry), "processDate(${entry.key}, a)")
entry.value = "99"
Utils.processDate(p, entry)
Assert.assertEquals("99", p.getProperty(entry.key), "processDate(${entry.key}, 99)")
entry.value = "now"
Utils.processDate(p, entry)
Assert.assertEquals("$day", p.getProperty(entry.key), "processDate(${entry.key}, now)")
// ADD
entry.operation = Operations.ADD
entry.value = "1"
Utils.processDate(p, entry)
Assert.assertEquals("${day+1}", p.getProperty(entry.key), "processDate(${entry.key}, now+1)")
entry.value = "2"
Utils.processDate(p, entry)
Assert.assertEquals("${day+3}", p.getProperty(entry.key), "processDate(${entry.key}, now+3)")
// SUBTRACT
entry.operation = Operations.SUBTRACT
entry.value = "3"
Utils.processDate(p, entry)
Assert.assertEquals("$day", p.getProperty(entry.key), "processDate(${entry.key}, now-3)")
entry.operation = Operations.SUBTRACT
entry.value = "2"
Utils.processDate(p, entry)
Assert.assertEquals("${day-2}", p.getProperty(entry.key), "processDate(${entry.key}, now-2)")
}
}