From 58d605271cb6488e9d86db6e6a5ff9fc27ad48ac Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Mon, 28 Aug 2023 17:45:16 -0700 Subject: [PATCH 1/7] Wherever a `String` gets into a `Snapshot` or `SnapshotValue`, make sure it only contains unix newlines. --- .../commonMain/kotlin/com/diffplug/selfie/SnapshotFile.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/selfie-lib/src/commonMain/kotlin/com/diffplug/selfie/SnapshotFile.kt b/selfie-lib/src/commonMain/kotlin/com/diffplug/selfie/SnapshotFile.kt index 862a6bb7..3136c255 100644 --- a/selfie-lib/src/commonMain/kotlin/com/diffplug/selfie/SnapshotFile.kt +++ b/selfie-lib/src/commonMain/kotlin/com/diffplug/selfie/SnapshotFile.kt @@ -38,7 +38,7 @@ sealed interface SnapshotValue { companion object { fun of(binary: ByteArray): SnapshotValue = SnapshotValueBinary(binary) - fun of(string: String): SnapshotValue = SnapshotValueString(string) + fun of(string: String): SnapshotValue = SnapshotValueString(unixNewlines(string)) } } @@ -66,7 +66,8 @@ data class Snapshot( get() = lensData fun lens(key: String, value: ByteArray) = lens(key, SnapshotValue.of(value)) fun lens(key: String, value: String) = lens(key, SnapshotValue.of(value)) - fun lens(key: String, value: SnapshotValue) = Snapshot(this.value, lensData.plus(key, value)) + fun lens(key: String, value: SnapshotValue) = + Snapshot(this.value, lensData.plus(unixNewlines(key), value)) override fun toString(): String = "[${value} ${lenses}]" companion object { @@ -82,6 +83,7 @@ private fun String.efficientReplace(find: String, replaceWith: String): String { val idx = this.indexOf(find) return if (idx == -1) this else this.replace(find, replaceWith) } +private fun unixNewlines(str: String) = str.efficientReplace("\r\n", "\n") class SnapshotFile { // this will probably become `` we'll cross that bridge when we get to it From 6f3f22971ca60634546532c91451fc7d1a94b3f1 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Mon, 28 Aug 2023 22:21:46 -0700 Subject: [PATCH 2/7] Unfinished scaffolding of SnapshotFile that can preserve windows newlines. --- .../commonMain/kotlin/com/diffplug/selfie/SnapshotFile.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/selfie-lib/src/commonMain/kotlin/com/diffplug/selfie/SnapshotFile.kt b/selfie-lib/src/commonMain/kotlin/com/diffplug/selfie/SnapshotFile.kt index 3136c255..edd4f74b 100644 --- a/selfie-lib/src/commonMain/kotlin/com/diffplug/selfie/SnapshotFile.kt +++ b/selfie-lib/src/commonMain/kotlin/com/diffplug/selfie/SnapshotFile.kt @@ -86,10 +86,14 @@ private fun String.efficientReplace(find: String, replaceWith: String): String { private fun unixNewlines(str: String) = str.efficientReplace("\r\n", "\n") class SnapshotFile { + internal var isUnixNewline = true // this will probably become `` we'll cross that bridge when we get to it var metadata: Map.Entry? = null var snapshots = ArrayMap.empty() - fun serialize(valueWriter: StringWriter) { + fun serialize(valueWriterRaw: StringWriter) { + val valueWriter = + if (isUnixNewline) valueWriterRaw + else StringWriter { valueWriterRaw.write(it.efficientReplace("\n", "\r\n")) } metadata?.let { writeKey(valueWriter, "📷 ${it.key}", null) writeValue(valueWriter, SnapshotValue.of(it.value)) @@ -152,6 +156,8 @@ class SnapshotFile { fun parse(valueReader: SnapshotValueReader): SnapshotFile { try { val result = SnapshotFile() + result.isUnixNewline = + TODO("""add internal method to SnapshotValueReader to query if newline is \n or \r\n""") val reader = SnapshotReader(valueReader) // only if the first value starts with 📷 if (reader.peekKey()?.startsWith(HEADER_PREFIX) == true) { From 68167707311b4c0015cf9b402b689a148c7c5676 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Mon, 28 Aug 2023 22:32:49 -0700 Subject: [PATCH 3/7] Unfinished scaffolding so that new snapshots are created with the correct newlines. --- .../kotlin/com/diffplug/selfie/SnapshotFile.kt | 11 ++++++++--- .../com/diffplug/selfie/junit5/SelfieConfig.kt | 12 ++++++++++-- .../selfie/junit5/SelfieTestExecutionListener.kt | 2 +- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/selfie-lib/src/commonMain/kotlin/com/diffplug/selfie/SnapshotFile.kt b/selfie-lib/src/commonMain/kotlin/com/diffplug/selfie/SnapshotFile.kt index edd4f74b..12ae015d 100644 --- a/selfie-lib/src/commonMain/kotlin/com/diffplug/selfie/SnapshotFile.kt +++ b/selfie-lib/src/commonMain/kotlin/com/diffplug/selfie/SnapshotFile.kt @@ -86,13 +86,13 @@ private fun String.efficientReplace(find: String, replaceWith: String): String { private fun unixNewlines(str: String) = str.efficientReplace("\r\n", "\n") class SnapshotFile { - internal var isUnixNewline = true + internal var unixNewlines = true // this will probably become `` we'll cross that bridge when we get to it var metadata: Map.Entry? = null var snapshots = ArrayMap.empty() fun serialize(valueWriterRaw: StringWriter) { val valueWriter = - if (isUnixNewline) valueWriterRaw + if (unixNewlines) valueWriterRaw else StringWriter { valueWriterRaw.write(it.efficientReplace("\n", "\r\n")) } metadata?.let { writeKey(valueWriter, "📷 ${it.key}", null) @@ -156,7 +156,7 @@ class SnapshotFile { fun parse(valueReader: SnapshotValueReader): SnapshotFile { try { val result = SnapshotFile() - result.isUnixNewline = + result.unixNewlines = TODO("""add internal method to SnapshotValueReader to query if newline is \n or \r\n""") val reader = SnapshotReader(valueReader) // only if the first value starts with 📷 @@ -173,6 +173,11 @@ class SnapshotFile { throw if (e is ParseException) e else ParseException(valueReader.lineReader, e) } } + fun createEmptyWithUnixNewlines(unixNewlines: Boolean): SnapshotFile { + val result = SnapshotFile() + result.unixNewlines = unixNewlines + return result + } } } diff --git a/selfie-runner-junit5/src/main/kotlin/com/diffplug/selfie/junit5/SelfieConfig.kt b/selfie-runner-junit5/src/main/kotlin/com/diffplug/selfie/junit5/SelfieConfig.kt index e03170af..eca1354d 100644 --- a/selfie-runner-junit5/src/main/kotlin/com/diffplug/selfie/junit5/SelfieConfig.kt +++ b/selfie-runner-junit5/src/main/kotlin/com/diffplug/selfie/junit5/SelfieConfig.kt @@ -19,7 +19,11 @@ import java.nio.file.Files import java.nio.file.Path import java.nio.file.Paths -internal class SnapshotFileLayout(val rootFolder: Path, val snapshotFolderName: String?) { +internal class SnapshotFileLayout( + val rootFolder: Path, + val snapshotFolderName: String?, + val unixNewlines: Boolean +) { val extension: String = ".ss" fun snapshotPathForClass(className: String): Path { val lastDot = className.lastIndexOf('.') @@ -69,7 +73,11 @@ internal class SnapshotFileLayout(val rootFolder: Path, val snapshotFolderName: selfieDotProp?.openStream()?.use { properties.load(selfieDotProp.openStream()) } val snapshotFolderName = snapshotFolderName(properties.getProperty("snapshot-dir")) val snapshotRootFolder = rootFolder(properties.getProperty("output-dir")) - return SnapshotFileLayout(snapshotRootFolder, snapshotFolderName) + // it's pretty easy to preserve the line endings of existing snapshot files, but it's + // a bit harder to create a fresh snapshot file with the correct line endings. + val unixNewlines: Boolean = + TODO("find the first file in the snapshot folder and check if it has unix newlines") + return SnapshotFileLayout(snapshotRootFolder, snapshotFolderName, unixNewlines) } private fun snapshotFolderName(snapshotDir: String?): String? { if (snapshotDir == null) { diff --git a/selfie-runner-junit5/src/main/kotlin/com/diffplug/selfie/junit5/SelfieTestExecutionListener.kt b/selfie-runner-junit5/src/main/kotlin/com/diffplug/selfie/junit5/SelfieTestExecutionListener.kt index 4b839517..49106c44 100644 --- a/selfie-runner-junit5/src/main/kotlin/com/diffplug/selfie/junit5/SelfieTestExecutionListener.kt +++ b/selfie-runner-junit5/src/main/kotlin/com/diffplug/selfie/junit5/SelfieTestExecutionListener.kt @@ -167,7 +167,7 @@ internal class ClassProgress(val className: String) { val content = Files.readAllBytes(snapshotPath) SnapshotFile.parse(SnapshotValueReader.of(content)) } else { - SnapshotFile() + SnapshotFile.createEmptyWithUnixNewlines(Router.layout!!.unixNewlines) } } return file!! From 530423efe02f82e8a44071575e7f6e069a397007 Mon Sep 17 00:00:00 2001 From: Ned Twigg Date: Mon, 28 Aug 2023 22:33:07 -0700 Subject: [PATCH 4/7] Add a test for carriage return handling. --- .../selfie/junit5/CarriageReturnTest.kt | 70 +++++++++++++++++++ .../undertest/junit5/UT_CarriageReturnTest.kt | 10 +++ 2 files changed, 80 insertions(+) create mode 100644 selfie-runner-junit5/src/test/kotlin/com/diffplug/selfie/junit5/CarriageReturnTest.kt create mode 100644 undertest-junit5/src/test/kotlin/undertest/junit5/UT_CarriageReturnTest.kt diff --git a/selfie-runner-junit5/src/test/kotlin/com/diffplug/selfie/junit5/CarriageReturnTest.kt b/selfie-runner-junit5/src/test/kotlin/com/diffplug/selfie/junit5/CarriageReturnTest.kt new file mode 100644 index 00000000..34a71ca8 --- /dev/null +++ b/selfie-runner-junit5/src/test/kotlin/com/diffplug/selfie/junit5/CarriageReturnTest.kt @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2023 DiffPlug + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.diffplug.selfie.junit5 + +import kotlin.test.Test +import org.junit.jupiter.api.MethodOrderer +import org.junit.jupiter.api.Order +import org.junit.jupiter.api.TestMethodOrder +import org.junitpioneer.jupiter.DisableIfTestFails + +/** Verify selfie's carriage-return handling. */ +@TestMethodOrder(MethodOrderer.OrderAnnotation::class) +@DisableIfTestFails +class CarriageReturnTest : Harness("undertest-junit5") { + @Test @Order(1) + fun noSelfie() { + ut_snapshot().deleteIfExists() + ut_snapshot().assertDoesNotExist() + } + val expectedContent = + """ + ╔═ git_makes_carriage_returns_unrepresentable ═╗ + hard + to + preserve + this + + ╔═ [end of file] ═╗ + + """ + .trimIndent() + + @Test @Order(2) + fun write_and_assert_ss_has_unix_newlines() { + gradleWriteSS() + ut_snapshot().assertContent(expectedContent) + } + + @Test @Order(3) + fun if_ss_has_cr_then_it_will_stay_cr() { + ut_snapshot().setContent("\r\n") + gradleWriteSS() + ut_snapshot().assertContent(expectedContent.replace("\n", "\r\n")) + } + + @Test @Order(4) + fun go_back_to_unix_and_it_stays_unix() { + ut_snapshot().setContent("\n") + gradleWriteSS() + ut_snapshot().assertContent(expectedContent) + } + + @Test @Order(5) + fun deleteSelfie() { + ut_snapshot().deleteIfExists() + } +} diff --git a/undertest-junit5/src/test/kotlin/undertest/junit5/UT_CarriageReturnTest.kt b/undertest-junit5/src/test/kotlin/undertest/junit5/UT_CarriageReturnTest.kt new file mode 100644 index 00000000..aa434dea --- /dev/null +++ b/undertest-junit5/src/test/kotlin/undertest/junit5/UT_CarriageReturnTest.kt @@ -0,0 +1,10 @@ +package undertest.junit5 + +import com.diffplug.selfie.expectSelfie +import kotlin.test.Test + +class UT_CarriageReturnTest { + @Test fun git_makes_carriage_returns_unrepresentable() { + expectSelfie("hard\r\nto\npreserve\r\nthis\r\n").toMatchDisk() + } +} From f90a8ccc35819283e4cbf626c779ee666505812f Mon Sep 17 00:00:00 2001 From: Edgar Espina Date: Sat, 9 Sep 2023 11:55:38 -0300 Subject: [PATCH 5/7] WIP: implement useUnixNewLines - redo jvm line reader to keep incremental reads and figure it out useUnixNewLines - still got some failures, but want to get feedback about the line reader --- .../com/diffplug/selfie/SnapshotFile.kt | 5 +- .../com/diffplug/selfie/SnapshotFile.js.kt | 1 + .../com/diffplug/selfie/SnapshotFile.jvm.kt | 60 ++++++++++++++- .../com/diffplug/selfie/LineReaderTest.kt | 77 +++++++++++++++++++ .../diffplug/selfie/junit5/SelfieConfig.kt | 13 +++- 5 files changed, 150 insertions(+), 6 deletions(-) create mode 100644 selfie-lib/src/jvmTest/kotlin/com/diffplug/selfie/LineReaderTest.kt diff --git a/selfie-lib/src/commonMain/kotlin/com/diffplug/selfie/SnapshotFile.kt b/selfie-lib/src/commonMain/kotlin/com/diffplug/selfie/SnapshotFile.kt index 83e1e8c2..e4fa0335 100644 --- a/selfie-lib/src/commonMain/kotlin/com/diffplug/selfie/SnapshotFile.kt +++ b/selfie-lib/src/commonMain/kotlin/com/diffplug/selfie/SnapshotFile.kt @@ -153,8 +153,7 @@ class SnapshotFile { fun parse(valueReader: SnapshotValueReader): SnapshotFile { try { val result = SnapshotFile() - result.unixNewlines = - TODO("""add internal method to SnapshotValueReader to query if newline is \n or \r\n""") + result.unixNewlines = valueReader.unixNewlines val reader = SnapshotReader(valueReader) // only if the first value starts with 📷 if (reader.peekKey()?.startsWith(HEADER_PREFIX) == true) { @@ -220,6 +219,7 @@ class SnapshotReader(val valueReader: SnapshotValueReader) { /** Provides the ability to parse a snapshot file incrementally. */ class SnapshotValueReader(val lineReader: LineReader) { var line: String? = null + val unixNewlines = lineReader.unixNewlines() /** The key of the next value, does not increment anything about the reader's state. */ fun peekKey(): String? { @@ -324,6 +324,7 @@ class SnapshotValueReader(val lineReader: LineReader) { expect class LineReader { fun getLineNumber(): Int fun readLine(): String? + fun unixNewlines(): Boolean companion object { fun forString(content: String): LineReader diff --git a/selfie-lib/src/jsMain/kotlin/com/diffplug/selfie/SnapshotFile.js.kt b/selfie-lib/src/jsMain/kotlin/com/diffplug/selfie/SnapshotFile.js.kt index aea33987..8b85719c 100644 --- a/selfie-lib/src/jsMain/kotlin/com/diffplug/selfie/SnapshotFile.js.kt +++ b/selfie-lib/src/jsMain/kotlin/com/diffplug/selfie/SnapshotFile.js.kt @@ -22,4 +22,5 @@ actual class LineReader { } actual fun getLineNumber(): Int = TODO() actual fun readLine(): String? = TODO() + actual fun unixNewlines(): Boolean = TODO() } diff --git a/selfie-lib/src/jvmMain/kotlin/com/diffplug/selfie/SnapshotFile.jvm.kt b/selfie-lib/src/jvmMain/kotlin/com/diffplug/selfie/SnapshotFile.jvm.kt index 1c0b4210..2f823e46 100644 --- a/selfie-lib/src/jvmMain/kotlin/com/diffplug/selfie/SnapshotFile.jvm.kt +++ b/selfie-lib/src/jvmMain/kotlin/com/diffplug/selfie/SnapshotFile.jvm.kt @@ -15,16 +15,74 @@ */ package com.diffplug.selfie +import java.io.BufferedReader import java.io.InputStreamReader import java.io.LineNumberReader import java.io.Reader import java.io.StringReader +import java.nio.CharBuffer import java.nio.charset.StandardCharsets -actual class LineReader(reader: Reader) : LineNumberReader(reader) { +actual class LineReader(reader: Reader) { + private val reader = LineTerminatorAware(LineTerminatorReader(reader)) + actual companion object { actual fun forString(content: String) = LineReader(StringReader(content)) actual fun forBinary(content: ByteArray) = LineReader(InputStreamReader(content.inputStream(), StandardCharsets.UTF_8)) } + actual fun getLineNumber(): Int = reader.lineNumber + actual fun readLine(): String? = reader.readLine() + actual fun unixNewlines(): Boolean = reader.lineTerminator.unixNewlines() +} + +/** + * Keep track of carriage return char to figure it out if we need unix new line or not. The first + * line is kept in memory until we require the next line. + */ +private open class LineTerminatorAware(val lineTerminator: LineTerminatorReader) : + LineNumberReader(lineTerminator) { + /** First line is initialized as soon as possible. */ + private var firstLine: String? = super.readLine() + override fun readLine(): String? { + if (this.firstLine != null) { + val result = this.firstLine + this.firstLine = null + return result + } + return super.readLine() + } +} + +/** + * Override all read operations to find the carriage return. We want to keep lazy/incremental reads. + */ +private class LineTerminatorReader(reader: Reader) : BufferedReader(reader) { + private val CR: Int = '\r'.code + private var unixNewlines = System.lineSeparator().equals("\n") + override fun read(cbuf: CharArray): Int { + val result = super.read(cbuf) + unixNewlines = cbuf.indexOf(CR.toChar()) == -1 + return result + } + override fun read(target: CharBuffer): Int { + val result = super.read(target) + unixNewlines = target.indexOf(CR.toChar()) == -1 + return result + } + override fun read(cbuf: CharArray, off: Int, len: Int): Int { + val result = super.read(cbuf, off, len) + unixNewlines = cbuf.indexOf(CR.toChar()) == -1 + return result + } + override fun read(): Int { + val ch = super.read() + if (ch == CR) { + unixNewlines = false + } + return ch + } + fun unixNewlines(): Boolean { + return unixNewlines + } } diff --git a/selfie-lib/src/jvmTest/kotlin/com/diffplug/selfie/LineReaderTest.kt b/selfie-lib/src/jvmTest/kotlin/com/diffplug/selfie/LineReaderTest.kt new file mode 100644 index 00000000..ed59e664 --- /dev/null +++ b/selfie-lib/src/jvmTest/kotlin/com/diffplug/selfie/LineReaderTest.kt @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2023 DiffPlug + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.diffplug.selfie + +import io.kotest.matchers.shouldBe +import kotlin.test.Test + +class LineReaderTest { + + @Test + fun shouldFindUnixSeparatorFromBinary() { + val reader = LineReader.forBinary("This is a new line\n".encodeToByteArray()) + reader.unixNewlines() shouldBe true + reader.readLine() shouldBe "This is a new line" + } + + @Test + fun shouldFindWindowsSeparatorFromBinary() { + val reader = LineReader.forBinary("This is a new line\r\n".encodeToByteArray()) + reader.unixNewlines() shouldBe false + reader.readLine() shouldBe "This is a new line" + } + + @Test + fun shouldFindUnixSeparatorFromString() { + val reader = LineReader.forString("This is a new line\n") + reader.unixNewlines() shouldBe true + reader.readLine() shouldBe "This is a new line" + } + + @Test + fun shouldFindWindowsSeparatorFromString() { + val reader = LineReader.forString("This is a new line\r\n") + reader.unixNewlines() shouldBe false + reader.readLine() shouldBe "This is a new line" + } + + @Test + fun shouldGetOSLineSeparatorWhenThereIsNone() { + val reader = LineReader.forBinary("This is a new line".encodeToByteArray()) + reader.unixNewlines() shouldBe System.lineSeparator().equals("\n") + reader.readLine() shouldBe "This is a new line" + } + + @Test + fun shouldReadNextLineWithoutProblem() { + val reader = LineReader.forBinary("First\r\nSecond\r\n".encodeToByteArray()) + reader.unixNewlines() shouldBe false + reader.readLine() shouldBe "First" + reader.unixNewlines() shouldBe false + reader.readLine() shouldBe "Second" + reader.unixNewlines() shouldBe false + } + + @Test + fun shouldUseFirstLineSeparatorAndIgnoreNext() { + val reader = LineReader.forBinary("First\r\nAnother separator\n".encodeToByteArray()) + reader.unixNewlines() shouldBe false + reader.readLine() shouldBe "First" + reader.unixNewlines() shouldBe false + reader.readLine() shouldBe "Another separator" + reader.unixNewlines() shouldBe false + } +} diff --git a/selfie-runner-junit5/src/main/kotlin/com/diffplug/selfie/junit5/SelfieConfig.kt b/selfie-runner-junit5/src/main/kotlin/com/diffplug/selfie/junit5/SelfieConfig.kt index eca1354d..8ed5007a 100644 --- a/selfie-runner-junit5/src/main/kotlin/com/diffplug/selfie/junit5/SelfieConfig.kt +++ b/selfie-runner-junit5/src/main/kotlin/com/diffplug/selfie/junit5/SelfieConfig.kt @@ -75,9 +75,16 @@ internal class SnapshotFileLayout( val snapshotRootFolder = rootFolder(properties.getProperty("output-dir")) // it's pretty easy to preserve the line endings of existing snapshot files, but it's // a bit harder to create a fresh snapshot file with the correct line endings. - val unixNewlines: Boolean = - TODO("find the first file in the snapshot folder and check if it has unix newlines") - return SnapshotFileLayout(snapshotRootFolder, snapshotFolderName, unixNewlines) + val candidate = + snapshotRootFolder + .resolve(snapshotFolderName!!) + .toFile() + .walkTopDown() + .maxDepth(1) + .filter { it.isFile } + .firstOrNull() + val cr = candidate?.readText()?.contains('\r') ?: System.lineSeparator().equals("\r\n") + return SnapshotFileLayout(snapshotRootFolder, snapshotFolderName, !cr) } private fun snapshotFolderName(snapshotDir: String?): String? { if (snapshotDir == null) { From c6128f03c5becc321353d9f2333d93320be4209b Mon Sep 17 00:00:00 2001 From: Edgar Espina Date: Sat, 9 Sep 2023 17:26:14 -0300 Subject: [PATCH 6/7] tests: fix carriage return tests - there was setting the content to just `\r\n` or `\n` produces an empty snapshot making the build unstable --- .../kotlin/com/diffplug/selfie/SnapshotFile.jvm.kt | 2 +- .../kotlin/com/diffplug/selfie/junit5/SelfieConfig.kt | 8 +++----- .../com/diffplug/selfie/junit5/CarriageReturnTest.kt | 7 ++++--- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/selfie-lib/src/jvmMain/kotlin/com/diffplug/selfie/SnapshotFile.jvm.kt b/selfie-lib/src/jvmMain/kotlin/com/diffplug/selfie/SnapshotFile.jvm.kt index 2f823e46..60d5cc4c 100644 --- a/selfie-lib/src/jvmMain/kotlin/com/diffplug/selfie/SnapshotFile.jvm.kt +++ b/selfie-lib/src/jvmMain/kotlin/com/diffplug/selfie/SnapshotFile.jvm.kt @@ -59,7 +59,7 @@ private open class LineTerminatorAware(val lineTerminator: LineTerminatorReader) */ private class LineTerminatorReader(reader: Reader) : BufferedReader(reader) { private val CR: Int = '\r'.code - private var unixNewlines = System.lineSeparator().equals("\n") + private var unixNewlines = true override fun read(cbuf: CharArray): Int { val result = super.read(cbuf) unixNewlines = cbuf.indexOf(CR.toChar()) == -1 diff --git a/selfie-runner-junit5/src/main/kotlin/com/diffplug/selfie/junit5/SelfieConfig.kt b/selfie-runner-junit5/src/main/kotlin/com/diffplug/selfie/junit5/SelfieConfig.kt index 8ed5007a..719bb6da 100644 --- a/selfie-runner-junit5/src/main/kotlin/com/diffplug/selfie/junit5/SelfieConfig.kt +++ b/selfie-runner-junit5/src/main/kotlin/com/diffplug/selfie/junit5/SelfieConfig.kt @@ -68,22 +68,20 @@ internal class SnapshotFileLayout( "src/test/scala", "src/test/resources") fun initialize(className: String): SnapshotFileLayout { - val selfieDotProp = SnapshotFileLayout.javaClass.getResource("/selfie.properties") + val selfieDotProp = SnapshotFileLayout::class.java.getResource("/selfie.properties") val properties = java.util.Properties() selfieDotProp?.openStream()?.use { properties.load(selfieDotProp.openStream()) } val snapshotFolderName = snapshotFolderName(properties.getProperty("snapshot-dir")) val snapshotRootFolder = rootFolder(properties.getProperty("output-dir")) // it's pretty easy to preserve the line endings of existing snapshot files, but it's // a bit harder to create a fresh snapshot file with the correct line endings. - val candidate = + val cr = snapshotRootFolder .resolve(snapshotFolderName!!) .toFile() .walkTopDown() - .maxDepth(1) .filter { it.isFile } - .firstOrNull() - val cr = candidate?.readText()?.contains('\r') ?: System.lineSeparator().equals("\r\n") + .any { it.readText().contains('\r') } return SnapshotFileLayout(snapshotRootFolder, snapshotFolderName, !cr) } private fun snapshotFolderName(snapshotDir: String?): String? { diff --git a/selfie-runner-junit5/src/test/kotlin/com/diffplug/selfie/junit5/CarriageReturnTest.kt b/selfie-runner-junit5/src/test/kotlin/com/diffplug/selfie/junit5/CarriageReturnTest.kt index 34a71ca8..27d2f932 100644 --- a/selfie-runner-junit5/src/test/kotlin/com/diffplug/selfie/junit5/CarriageReturnTest.kt +++ b/selfie-runner-junit5/src/test/kotlin/com/diffplug/selfie/junit5/CarriageReturnTest.kt @@ -51,14 +51,15 @@ class CarriageReturnTest : Harness("undertest-junit5") { @Test @Order(3) fun if_ss_has_cr_then_it_will_stay_cr() { - ut_snapshot().setContent("\r\n") + val contentWithCr = expectedContent.replace("\n", "\r\n") + ut_snapshot().setContent(contentWithCr) gradleWriteSS() - ut_snapshot().assertContent(expectedContent.replace("\n", "\r\n")) + ut_snapshot().assertContent(contentWithCr) } @Test @Order(4) fun go_back_to_unix_and_it_stays_unix() { - ut_snapshot().setContent("\n") + ut_snapshot().setContent(expectedContent) gradleWriteSS() ut_snapshot().assertContent(expectedContent) } From 3f951d6e7bb551ff9658769ca685ced018c0b69c Mon Sep 17 00:00:00 2001 From: Edgar Espina Date: Sat, 9 Sep 2023 20:32:47 -0300 Subject: [PATCH 7/7] tests: fix LineReaderTest - it must assume always unixline --- .../src/jvmTest/kotlin/com/diffplug/selfie/LineReaderTest.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/selfie-lib/src/jvmTest/kotlin/com/diffplug/selfie/LineReaderTest.kt b/selfie-lib/src/jvmTest/kotlin/com/diffplug/selfie/LineReaderTest.kt index ed59e664..b844a41b 100644 --- a/selfie-lib/src/jvmTest/kotlin/com/diffplug/selfie/LineReaderTest.kt +++ b/selfie-lib/src/jvmTest/kotlin/com/diffplug/selfie/LineReaderTest.kt @@ -49,9 +49,9 @@ class LineReaderTest { } @Test - fun shouldGetOSLineSeparatorWhenThereIsNone() { + fun shouldGetUnixLineSeparatorWhenThereIsNone() { val reader = LineReader.forBinary("This is a new line".encodeToByteArray()) - reader.unixNewlines() shouldBe System.lineSeparator().equals("\n") + reader.unixNewlines() shouldBe true reader.readLine() shouldBe "This is a new line" }