diff --git a/platform/built-in-server/testSrc/TestManager.kt b/platform/built-in-server/testSrc/TestManager.kt index 05f13c915c89..be3fc2ef57e3 100644 --- a/platform/built-in-server/testSrc/TestManager.kt +++ b/platform/built-in-server/testSrc/TestManager.kt @@ -1,5 +1,6 @@ package org.jetbrains.ide +import com.intellij.openapi.application.invokeAndWaitIfNeed import com.intellij.openapi.application.writeAction import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.roots.ModuleRootModificationUtil @@ -7,7 +8,6 @@ import com.intellij.openapi.util.io.FileUtilRt import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.vfs.VirtualFile import com.intellij.testFramework.fixtures.IdeaProjectTestFixture -import org.jetbrains.testFramework.invokeAndWaitIfNeed import org.junit.rules.TestWatcher import org.junit.runner.Description import java.io.File diff --git a/platform/core-impl/src/com/intellij/openapi/application/actions.kt b/platform/core-impl/src/com/intellij/openapi/application/actions.kt index df6f89b514bc..4be236085b50 100644 --- a/platform/core-impl/src/com/intellij/openapi/application/actions.kt +++ b/platform/core-impl/src/com/intellij/openapi/application/actions.kt @@ -15,6 +15,8 @@ */ package com.intellij.openapi.application +import javax.swing.SwingUtilities + public inline fun writeAction(runnable: () -> Unit) { val token = WriteAction.start() try { @@ -23,4 +25,14 @@ public inline fun writeAction(runnable: () -> Unit) { finally { token.finish() } -} \ No newline at end of file +} + +public fun invokeAndWaitIfNeed(runnable: () -> Unit) { + val app = ApplicationManager.getApplication() + if (app == null) { + if (SwingUtilities.isEventDispatchThread()) runnable() else SwingUtilities.invokeAndWait(runnable) + } + else { + if (app.isDispatchThread()) runnable() else app.invokeAndWait(runnable, ModalityState.any()) + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StreamProvider.kt b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StreamProvider.kt index 86a31f2185bc..df166e62a043 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StreamProvider.kt +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StreamProvider.kt @@ -43,7 +43,7 @@ public interface StreamProvider { /** * You must close passed input stream. */ - public open fun processChildren(path: String, roamingType: RoamingType, filter: (name: String) -> Boolean, processor: (name: String, input: InputStream) -> Boolean) { + public open fun processChildren(path: String, roamingType: RoamingType, filter: (name: String) -> Boolean, processor: (name: String, input: InputStream, readOnly: Boolean) -> Boolean) { for (name in listSubFiles(path, roamingType)) { if (!filter(name)) { continue @@ -59,7 +59,7 @@ public interface StreamProvider { } - if (input != null && !processor(name, input)) { + if (input != null && !processor(name, input, false)) { break } } diff --git a/platform/platform-impl/src/com/intellij/openapi/options/SchemeManagerImpl.kt b/platform/platform-impl/src/com/intellij/openapi/options/SchemeManagerImpl.kt index 9f476ad7e979..f2e4ac8eac7a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/SchemeManagerImpl.kt +++ b/platform/platform-impl/src/com/intellij/openapi/options/SchemeManagerImpl.kt @@ -61,7 +61,7 @@ public class SchemeManagerImpl(private val private val provider: StreamProvider?, private val ioDirectory: File) : SchemesManager(), SafeWriteRequestor { private val schemes = ArrayList() - private val bundledExternalizableSchemes = THashMap() + private val readOnlyExternalizableSchemes = THashMap() private var currentScheme: T? = null private var currentSchemeName: String? = null @@ -215,7 +215,7 @@ public class SchemeManagerImpl(private val @suppress("UNCHECKED_CAST") val oldInfo = schemeToInfo.put(scheme as E, info) LOG.assertTrue(oldInfo == null) - val oldScheme = bundledExternalizableSchemes.put(scheme.getName(), scheme) + val oldScheme = readOnlyExternalizableSchemes.put(scheme.getName(), scheme) if (oldScheme != null) { LOG.warn("Duplicated scheme ${scheme.getName()} - old: $oldScheme, new $scheme") } @@ -250,8 +250,11 @@ public class SchemeManagerImpl(private val override fun loadSchemes(): Collection { val newSchemesOffset = schemes.size() if (provider != null && provider.isEnabled()) { - provider.processChildren(fileSpec, roamingType, { canRead(it) }) { name, input -> - loadScheme(name, input, true) + provider.processChildren(fileSpec, roamingType, { canRead(it) }) { name, input, readOnly -> + val scheme = loadScheme(name, input, true) + if (readOnly && scheme != null) { + readOnlyExternalizableSchemes.put(scheme.name, scheme) + } true } } @@ -304,7 +307,7 @@ public class SchemeManagerImpl(private val } private fun isOverwriteOnLoad(existingScheme: E): Boolean { - if (bundledExternalizableSchemes.get(existingScheme.getName()) === existingScheme) { + if (readOnlyExternalizableSchemes.get(existingScheme.getName()) === existingScheme) { // so, bundled scheme is shadowed return true } @@ -488,7 +491,7 @@ public class SchemeManagerImpl(private val } // save only if scheme differs from bundled - val bundledScheme = bundledExternalizableSchemes.get(scheme.getName()) + val bundledScheme = readOnlyExternalizableSchemes.get(scheme.getName()) if (bundledScheme != null && schemeToInfo.get(bundledScheme)!!.hash == newHash) { externalInfo?.scheduleDelete() return @@ -651,7 +654,7 @@ public class SchemeManagerImpl(private val schemeToInfo.retainEntries(object : TObjectObjectProcedure { override fun execute(scheme: E, info: ExternalInfo): Boolean { - if (bundledExternalizableSchemes.get(scheme.getName()) == scheme) { + if (readOnlyExternalizableSchemes.get(scheme.getName()) == scheme) { return true } @@ -731,9 +734,7 @@ public class SchemeManagerImpl(private val schemeToInfo.clear() } - override fun getAllSchemes(): List { - return Collections.unmodifiableList(schemes) - } + override fun getAllSchemes() = Collections.unmodifiableList(schemes) override fun findSchemeByName(schemeName: String): T? { for (scheme in schemes) { @@ -789,7 +790,7 @@ public class SchemeManagerImpl(private val return names } - override fun isMetadataEditable(scheme: E) = !bundledExternalizableSchemes.containsKey(scheme.name) + override fun isMetadataEditable(scheme: E) = !readOnlyExternalizableSchemes.containsKey(scheme.name) private class ExternalInfo(var fileNameWithoutExtension: String, var fileExtension: String?) { // we keep it to detect rename diff --git a/platform/platform-tests/testData/options/different-extensions/1.icls b/platform/platform-tests/testData/options/different-extensions/1.icls new file mode 100644 index 000000000000..2b2964d3870c --- /dev/null +++ b/platform/platform-tests/testData/options/different-extensions/1.icls @@ -0,0 +1 @@ + diff --git a/platform/platform-tests/testData/options/different-extensions/1.xml b/platform/platform-tests/testData/options/different-extensions/1.xml new file mode 100644 index 000000000000..22a3a0bd0441 --- /dev/null +++ b/platform/platform-tests/testData/options/different-extensions/1.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/platform/platform-tests/testData/options/options/1.xml b/platform/platform-tests/testData/options/options/1.xml new file mode 100644 index 000000000000..e4c594a71fec --- /dev/null +++ b/platform/platform-tests/testData/options/options/1.xml @@ -0,0 +1 @@ + diff --git a/platform/platform-tests/testData/options/options1/1.xml b/platform/platform-tests/testData/options/options1/1.xml new file mode 100644 index 000000000000..c023fb61fd3d --- /dev/null +++ b/platform/platform-tests/testData/options/options1/1.xml @@ -0,0 +1 @@ + diff --git a/platform/platform-tests/testData/options/options1/2.xml b/platform/platform-tests/testData/options/options1/2.xml new file mode 100644 index 000000000000..e5b1786c1ad0 --- /dev/null +++ b/platform/platform-tests/testData/options/options1/2.xml @@ -0,0 +1 @@ + diff --git a/platform/platform-tests/testSrc/bundledSchemes/default.xml b/platform/platform-tests/testSrc/bundledSchemes/default.xml new file mode 100644 index 000000000000..0cb9dad410e4 --- /dev/null +++ b/platform/platform-tests/testSrc/bundledSchemes/default.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/platform/platform-tests/testSrc/com/intellij/options/MockStreamProvider.kt b/platform/platform-tests/testSrc/com/intellij/options/MockStreamProvider.kt new file mode 100644 index 000000000000..e7ed0ff3b495 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/options/MockStreamProvider.kt @@ -0,0 +1,40 @@ +package com.intellij.options + +import com.intellij.openapi.components.RoamingType +import com.intellij.openapi.components.impl.stores.StreamProvider +import com.intellij.openapi.util.io.FileUtil +import com.intellij.util.SmartList +import java.io.File +import java.io.FileInputStream +import java.io.InputStream + +class MockStreamProvider(private val myBaseDir: File) : StreamProvider { + override fun isApplicable(fileSpec: String, roamingType: RoamingType) = roamingType === RoamingType.PER_USER + + override fun saveContent(fileSpec: String, content: ByteArray, size: Int, roamingType: RoamingType) { + FileUtil.writeToFile(File(myBaseDir, fileSpec), content, 0, size) + } + + override fun loadContent(fileSpec: String, roamingType: RoamingType): InputStream? { + val file = File(myBaseDir, fileSpec) + //noinspection IOResourceOpenedButNotSafelyClosed + return if (file.exists()) FileInputStream(file) else null + } + + override fun listSubFiles(fileSpec: String, roamingType: RoamingType): Collection { + if (roamingType !== RoamingType.PER_USER) { + return emptyList() + } + + val files = File(myBaseDir, fileSpec).listFiles() ?: return emptyList() + val names = SmartList() + for (file in files) { + names.add(file.getName()) + } + return names + } + + override fun delete(fileSpec: String, roamingType: RoamingType) { + FileUtil.delete(File(myBaseDir, fileSpec)) + } +} diff --git a/platform/platform-tests/testSrc/com/intellij/options/SchemeManagerTest.kt b/platform/platform-tests/testSrc/com/intellij/options/SchemeManagerTest.kt new file mode 100644 index 000000000000..2cb9d57572d9 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/options/SchemeManagerTest.kt @@ -0,0 +1,368 @@ +package com.intellij.options + +import com.intellij.openapi.application.invokeAndWaitIfNeed +import com.intellij.openapi.components.RoamingType +import com.intellij.openapi.options.BaseSchemeProcessor +import com.intellij.openapi.options.ExternalizableScheme +import com.intellij.openapi.options.SchemeManagerImpl +import com.intellij.openapi.util.JDOMUtil +import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream +import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.util.text.StringUtil +import com.intellij.testFramework.PlatformTestUtil +import com.intellij.util.SmartList +import com.intellij.util.lang.CompoundRuntimeException +import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters +import com.intellij.util.xmlb.XmlSerializer +import com.intellij.util.xmlb.annotations.Attribute +import com.intellij.util.xmlb.annotations.Tag +import com.intellij.util.xmlb.annotations.Transient +import gnu.trove.THashMap +import org.hamcrest.CoreMatchers.equalTo +import org.hamcrest.CoreMatchers.not +import org.hamcrest.CoreMatchers.notNullValue +import org.hamcrest.CoreMatchers.sameInstance +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.collection.IsMapContaining.hasKey +import org.jdom.Element +import org.jetbrains.testFramework.FixtureRule +import org.jetbrains.testFramework.TemporaryDirectory +import org.jetbrains.testFramework.exists +import org.junit.Rule +import org.junit.Test +import java.io.File + +val FILE_SPEC = "REMOTE" + +class SchemeManagerTest { + private val fixtureManager = FixtureRule() + public Rule fun getFixtureManager(): FixtureRule = fixtureManager + + private val tempDirManager = TemporaryDirectory() + public Rule fun getTemporaryFolder(): TemporaryDirectory = tempDirManager + + private var localBaseDir: File? = null + private var remoteBaseDir: File? = null + + private fun getTestDataPath() = PlatformTestUtil.getCommunityPath().replace(File.separatorChar, '/') + "/platform/platform-tests/testData/options" + + public Test fun testLoadSchemes() { + doLoadSaveTest("options1", "1->first;2->second") + } + + public Test fun testLoadSimpleSchemes() { + doLoadSaveTest("options", "1->1") + } + + public Test fun testDeleteScheme() { + val manager = createAndLoad("options1") + manager.removeScheme(TestScheme("first")) + manager.save() + + checkSchemes("2->second") + } + + public Test fun testRenameScheme() { + val manager = createAndLoad("options1") + + val scheme = manager.findSchemeByName("first") + assertThat(scheme, notNullValue()) + assert(scheme != null) + scheme!!.setName("renamed") + manager.save() + + checkSchemes("2->second;renamed->renamed") + } + + public Test fun testRenameScheme2() { + val manager = createAndLoad("options1") + + val first = manager.findSchemeByName("first") + assertThat(first, notNullValue()) + assert(first != null) + first!!.setName("2") + val second = manager.findSchemeByName("second") + assertThat(second, notNullValue()) + assert(second != null) + second!!.setName("1") + manager.save() + + checkSchemes("1->1;2->2") + } + + public Test fun testDeleteRenamedScheme() { + val manager = createAndLoad("options1") + + val firstScheme = manager.findSchemeByName("first") + assertThat(firstScheme, notNullValue()) + assert(firstScheme != null) + firstScheme!!.setName("first_renamed") + manager.save() + + checkSchemes(File(remoteBaseDir, "REMOTE"), "first_renamed->first_renamed;2->second", true) + checkSchemes(localBaseDir!!, "", false) + + firstScheme.setName("first_renamed2") + manager.removeScheme(firstScheme) + manager.save() + + checkSchemes(File(remoteBaseDir, "REMOTE"), "2->second", true) + checkSchemes(localBaseDir!!, "", false) + } + + public Test fun testDeleteAndCreateSchemeWithTheSameName() { + val manager = createAndLoad("options1") + val firstScheme = manager.findSchemeByName("first") + assertThat(firstScheme, notNullValue()) + + manager.removeScheme(firstScheme!!) + manager.addScheme(TestScheme("first")) + manager.save() + checkSchemes("2->second;first->first") + } + + public Test fun testGenerateUniqueSchemeName() { + val manager = createAndLoad("options1") + val scheme = TestScheme("first") + manager.addNewScheme(scheme, false) + + assertThat("first2", equalTo(scheme.getName())) + } + + public Test fun `different extensions`() { + val dir = tempDirManager.newDirectory() + FileUtil.copyDir(File("${getTestDataPath()}/different-extensions"), dir, false) + val schemesManager = SchemeManagerImpl(FILE_SPEC, object: TestSchemesProcessor() { + override fun isUpgradeNeeded() = true + + override fun getSchemeExtension() = ".icls" + }, RoamingType.PER_USER, null, dir) + schemesManager.loadSchemes() + val schemes = schemesManager.getAllSchemes() + assertThat(schemes.size(), equalTo(1)) + val scheme = schemes.get(0) + assertThat(scheme.data, equalTo("true")) + + assertThat(File(dir, "1.icls"), exists()) + assertThat(File(dir, "1.xml"), exists()) + + scheme.data = "newTrue" + save(schemesManager) + + assertThat(File(dir, "1.icls"), exists()) + assertThat(File(dir, "1.xml"), not(exists())) + } + + public Test fun setSchemes() { + val dir = tempDirManager.newDirectory() + val schemesManager = createSchemeManager(dir) + schemesManager.loadSchemes() + assertThat(schemesManager.getAllSchemes().isEmpty(), equalTo(true)) + + val scheme = TestScheme("s1") + schemesManager.setSchemes(listOf(scheme)) + + val schemes = schemesManager.getAllSchemes() + assertThat(schemes.size(), equalTo(1)) + assertThat(schemes.get(0), sameInstance(scheme)) + + assertThat(File(dir, "s1.xml"), not(exists())) + + scheme.data = "newTrue" + save(schemesManager) + + assertThat(File(dir, "s1.xml"), exists()) + + schemesManager.setSchemes(emptyList()) + + save(schemesManager) + + assertThat(dir, not(exists())) + } + + public Test fun `save only if scheme differs from bundled`() { + val dir = tempDirManager.newDirectory() + var schemeManager = createSchemeManager(dir) + val converter: (Element) -> TestScheme = { XmlSerializer.deserialize(it, javaClass())!! } + val bundledPath = "/bundledSchemes/default" + schemeManager.loadBundledScheme(bundledPath, this, converter) + var schemes = schemeManager.getAllSchemes() + assertThat(schemes.size(), equalTo(1)) + val customScheme = TestScheme("default") + assertThat(schemes.get(0), equalTo(customScheme)) + + save(schemeManager) + assertThat(dir, not(exists())) + + save(schemeManager) + schemeManager.setSchemes(listOf(customScheme)) + assertThat(dir, not(exists())) + + schemes = schemeManager.getAllSchemes() + assertThat(schemes.size(), equalTo(1)) + assertThat(schemes.get(0), sameInstance(customScheme)) + + customScheme.data = "foo" + save(schemeManager) + val schemeFile = File(dir, "default.xml") + assertThat(schemeFile, exists()) + + schemeManager = createSchemeManager(dir) + schemeManager.loadBundledScheme(bundledPath, this, converter) + schemeManager.loadSchemes() + + schemes = schemeManager.getAllSchemes() + assertThat(schemes.get(0), equalTo(customScheme)) + } + + private fun createSchemeManager(dir: File) = SchemeManagerImpl(FILE_SPEC, TestSchemesProcessor(), RoamingType.PER_USER, null, dir) + + public Test fun `don't remove dir if no schemes but at least one non-hidden file exists`() { + val dir = tempDirManager.newDirectory() + val schemesManager = SchemeManagerImpl(FILE_SPEC, TestSchemesProcessor(), RoamingType.PER_USER, null, dir) + + val scheme = TestScheme("s1") + schemesManager.setSchemes(listOf(scheme)) + + save(schemesManager) + + val schemeFile = File(dir, "s1.xml") + assertThat(schemeFile.exists(), equalTo(true)) + + schemesManager.setSchemes(emptyList()) + + FileUtil.writeToFile(File(dir, "empty"), byteArrayOf()) + + save(schemesManager) + + assertThat(schemeFile.exists(), equalTo(false)) + assertThat(dir.exists(), equalTo(true)) + } + + public Test fun rename() { + val dir = tempDirManager.newDirectory() + val schemesManager = SchemeManagerImpl(FILE_SPEC, TestSchemesProcessor(), RoamingType.PER_USER, null, dir) + schemesManager.loadSchemes() + assertThat(schemesManager.getAllSchemes().isEmpty(), equalTo(true)) + + val scheme = TestScheme("s1") + schemesManager.setSchemes(listOf(scheme)) + + val schemes = schemesManager.getAllSchemes() + assertThat(schemes.size(), equalTo(1)) + assertThat(schemes.get(0), sameInstance(scheme)) + + assertThat(File(dir, "s1.xml").exists(), equalTo(false)) + + scheme.data = "newTrue" + save(schemesManager) + + assertThat(File(dir, "s1.xml").exists(), equalTo(true)) + + scheme.setName("s2") + + save(schemesManager) + + assertThat(File(dir, "s1.xml").exists(), equalTo(false)) + assertThat(File(dir, "s2.xml").exists(), equalTo(true)) + } + + private fun save(schemeManager: SchemeManagerImpl) { + invokeAndWaitIfNeed { + schemeManager.save() + } + } + + private fun createAndLoad(testData: String): SchemeManagerImpl { + createTempFiles(testData) + return createAndLoad() + } + + private fun doLoadSaveTest(testData: String, expected: String, localExpected: String = "") { + val schemesManager = createAndLoad(testData) + schemesManager.save() + checkSchemes(File(remoteBaseDir, "REMOTE"), expected, true) + checkSchemes(localBaseDir!!, localExpected, false) + } + + private fun checkSchemes(expected: String) { + checkSchemes(File(remoteBaseDir, "REMOTE"), expected, true) + checkSchemes(localBaseDir!!, "", false) + } + + private fun createAndLoad(): SchemeManagerImpl { + val schemesManager = SchemeManagerImpl(FILE_SPEC, TestSchemesProcessor(), RoamingType.PER_USER, MockStreamProvider(remoteBaseDir!!), localBaseDir!!) + schemesManager.loadSchemes() + return schemesManager + } + + private fun createTempFiles(testData: String) { + val temp = tempDirManager.newDirectory() + localBaseDir = File(temp, "__local") + remoteBaseDir = temp + FileUtil.copyDir(File("${getTestDataPath()}/$testData"), File(temp, "REMOTE")) + } +} + +private fun checkSchemes(baseDir: File, expected: String, ignoreDeleted: Boolean) { + val filesToScheme = StringUtil.split(expected, ";") + val fileToSchemeMap = THashMap() + for (fileToScheme in filesToScheme) { + val index = fileToScheme.indexOf("->") + fileToSchemeMap.put(fileToScheme.substring(0, index), fileToScheme.substring(index + 2)) + } + + val files = baseDir.listFiles() + if (files != null) { + for (file in files) { + val fileName = FileUtil.getNameWithoutExtension(file) + if ("--deleted" == fileName && ignoreDeleted) { + assertThat>(fileToSchemeMap, hasKey(fileName)) + } + } + } + + for (file in fileToSchemeMap.keySet()) { + assertThat(File(baseDir, "$file.xml").isFile(), equalTo(true)) + } + + if (files != null) { + val schemesProcessor = TestSchemesProcessor() + for (file in files) { + val fileName = FileUtil.getNameWithoutExtension(file) + val scheme = schemesProcessor.readScheme(JDOMUtil.load(file), true) + assertThat(fileToSchemeMap.get(fileName), equalTo(scheme!!.getName())) + } + } +} + +public data Tag("scheme") class TestScheme(Attribute private var name: String = "", Attribute var data: String? = null) : ExternalizableScheme { + override fun getName() = name + + override Transient fun setName(newName: String) { + name = newName + } + + @suppress("DEPRECATED_SYMBOL_WITH_MESSAGE") + override fun getExternalInfo() = null +} + +public open class TestSchemesProcessor : BaseSchemeProcessor() { + override fun readScheme(element: Element) = XmlSerializer.deserialize(element, javaClass()) + + override fun writeScheme(scheme: TestScheme) = scheme.serialize() +} + +fun SchemeManagerImpl<*, *>.save() { + val errors = SmartList() + save(errors) + CompoundRuntimeException.doThrow(errors) +} + +public fun T.serialize(): Element = XmlSerializer.serialize(this, SkipDefaultValuesSerializationFilters()) + +public fun Element.toByteArray(): ByteArray { + val out = BufferExposingByteArrayOutputStream(512) + JDOMUtil.writeParent(this, out, "\n") + return out.toByteArray() +} \ No newline at end of file diff --git a/platform/testFramework/testSrc/FixtureRule.kt b/platform/testFramework/testSrc/FixtureRule.kt index dcca0ef2d24c..06506fa0c744 100644 --- a/platform/testFramework/testSrc/FixtureRule.kt +++ b/platform/testFramework/testSrc/FixtureRule.kt @@ -15,14 +15,10 @@ */ package org.jetbrains.testFramework +import com.intellij.openapi.application.invokeAndWaitIfNeed import com.intellij.testFramework.UsefulTestCase import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory import org.junit.rules.ExternalResource -import javax.swing.SwingUtilities - -public fun invokeAndWaitIfNeed(runnable: () -> Unit) { - if (SwingUtilities.isEventDispatchThread()) runnable() else SwingUtilities.invokeAndWait(runnable) -} public class FixtureRule() : ExternalResource() { val projectFixture = IdeaTestFixtureFactory.getFixtureFactory().createLightFixtureBuilder().getFixture()