@Test public void nodesOutsideTheMountsAreIgnored() throws CommitFailedException { MountInfoProvider mip = Mounts.newBuilder().readOnlyMount("libs", "/libs").build(); NodeStore globalStore = new MemoryNodeStore(); NodeStore libsStore = new MemoryNodeStore();
@Before public void initStore() throws Exception { mip = Mounts.newBuilder() .readOnlyMount("temp", "/tmp") .readOnlyMount("deep", "/libs/mount") .readOnlyMount("empty", "/nowhere") .readOnlyMount("readOnly", "/readOnly") .build();
@Test public void reportedNodesAreWrapped() { Mounts.Builder mipBuilder = Mounts.newBuilder(); mipBuilder.readOnlyMount("libs", "/libs"); MountInfoProvider mip = mipBuilder.build();
@Test public void multipleContributingStores() { MountInfoProvider mip = Mounts.newBuilder().readOnlyMount("libs", "/libs", "/libs1", "/libs2", "/libs3", "/libs4").build(); NodeStore globalStore = new MemoryNodeStore(); NodeStore libsStore = new MemoryNodeStore();
@Before public void prepare() throws Exception { MountInfoProvider mip = Mounts.newBuilder().readOnlyMount("ro", "/private").build();
.readOnlyMount("foo", "/readOnly") .build();
@Test public void onlyPropertiesOnMainNodesAreCompared() throws CommitFailedException { MountInfoProvider mip = Mounts.newBuilder().readOnlyMount("libs", "/libs").build(); NodeStore globalStore = new MemoryNodeStore(); NodeStore libsStore = new MemoryNodeStore(); List<MountedNodeStore> mounts = Lists.newArrayList(); mounts.add(new MountedNodeStore(mip.getMountByName("libs"), libsStore)); CompositeNodeStore compositeNodeStore = new CompositeNodeStore(mip, globalStore, mounts); NodeState empty = compositeNodeStore.getRoot(); NodeBuilder builder = globalStore.getRoot().builder(); builder.setProperty("global-prop-1", "val"); builder.setProperty("global-prop-2", "val"); globalStore.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY); NodeBuilder libsBuilder = libsStore.getRoot().builder(); libsBuilder.setProperty("libs-prop-1", "val"); libsBuilder.setProperty("libs-prop-2", "val"); libsStore.merge(libsBuilder, EmptyHook.INSTANCE, CommitInfo.EMPTY); NodeState modified = compositeNodeStore.getRoot(); final Set<String> addedProperties = newHashSet(); modified.compareAgainstBaseState(empty, new DefaultNodeStateDiff() { @Override public boolean propertyAdded(PropertyState after) { addedProperties.add(after.getName()); return true; } }); assertEquals(ImmutableSet.of("global-prop-1", "global-prop-2"), addedProperties); }
@Test public void testShouldBeComposite() { MountInfoProvider mip = Mounts.newBuilder() .mount("libs", true, Arrays.asList( "/oak:index/*$" "/jcr:system/rep:permissionStore/oak:mount-libs-crx.default") .build(); CompositionContext ctx = new CompositionContext(mip, null, Collections.emptyList(), CompositeNodeStoreMonitor.EMPTY_INSTANCE, CompositeNodeStoreMonitor.EMPTY_INSTANCE);
@Test public void mountWithCommitInWritableMount() throws Exception{ NodeState root = INITIAL_CONTENT; // Add index definition NodeBuilder builder = root.builder(); NodeBuilder index = createIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo", true, false, ImmutableSet.of("foo"), null); index.setProperty("entryCount", -1); NodeState before = builder.getNodeState(); // Add some content and process it through the property index hook builder.child("content").setProperty("foo", "abc"); NodeState after = builder.getNodeState(); MountInfoProvider mip = Mounts.newBuilder() .readOnlyMount("foo", "/readOnly") .build(); CompositeHook hook = new CompositeHook( new EditorHook(new IndexUpdateProvider(new PropertyIndexEditorProvider().with(mip))), new EditorHook(new ValidatorProvider(){ protected Validator getRootValidator(NodeState before, NodeState after, CommitInfo info) { return new PrivateStoreValidator("/", mip); } }) ); NodeState indexed = hook.processCommit(before, after, CommitInfo.EMPTY); Mount defMount = mip.getDefaultMount(); assertTrue(getNode(indexed, pathInIndex(defMount, "/oak:index/foo", "/content", "abc")).exists()); }
@Test public void referenceHandlingWithMounts() throws Exception{ NodeState root = INITIAL_CONTENT; NodeBuilder builder = root.builder(); NodeState before = builder.getNodeState(); builder.child("a").child("x").setProperty(createProperty("foo", "u1", Type.REFERENCE)); builder.child("b").setProperty(createProperty("foo", "u1", Type.REFERENCE)); builder.child("c").setProperty(createProperty("foo", "u1", Type.WEAKREFERENCE)); builder.child("d").setProperty(createProperty("foo", "u2", Type.WEAKREFERENCE)); builder.child("a").child("y").setProperty(createProperty("foo", "u1", Type.WEAKREFERENCE)); NodeState after = builder.getNodeState(); MountInfoProvider mip = Mounts.newBuilder() .mount("foo", "/a") .build(); EditorHook hook = new EditorHook( new IndexUpdateProvider(new ReferenceEditorProvider().with(mip))); ReferenceIndex referenceIndex = new ReferenceIndex(mip); NodeState indexed = hook.processCommit(before, after, CommitInfo.EMPTY); FilterImpl f = createFilter(indexed, NT_BASE); f.restrictProperty("*", Operator.EQUAL, newReference("u1"), PropertyType.REFERENCE); // System.out.println(NodeStateUtils.toString(NodeStateUtils.getNode(indexed, "/oak:index/reference"))); assertFilter(f, referenceIndex, indexed, of("/a/x", "/b")); FilterImpl f2 = createFilter(indexed, NT_BASE); f2.restrictProperty("*", Operator.EQUAL, newReference("u1"), PropertyType.WEAKREFERENCE); assertFilter(f2, referenceIndex, indexed, of("/c", "/a/y")); }
@Test public void referenceableNodeInWhitelistIsSkipped() throws CommitFailedException { MemoryNodeStore root = new MemoryNodeStore(); MemoryNodeStore mount = new MemoryNodeStore(); NodeBuilder builder = mount.getRoot().builder(); builder.child("first") .setProperty(PropertyStates.createProperty(JcrConstants.JCR_PRIMARYTYPE, JcrConstants.NT_RESOURCE, Type.NAME)) .setProperty(PropertyStates.createProperty(JcrConstants.JCR_MIXINTYPES, Collections.singletonList(JcrConstants.MIX_REFERENCEABLE), Type.NAMES)) .setProperty(JcrConstants.JCR_UUID, UUID.randomUUID().toString()); mount.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY); MountInfoProvider mip = Mounts.newBuilder() .readOnlyMount("first", "/first") .build(); NodeTypeMountedNodeStoreChecker checker = new NodeTypeMountedNodeStoreChecker(JcrConstants.MIX_REFERENCEABLE, "test error", JcrConstants.NT_RESOURCE); Context context = checker.createContext(root, mip); ErrorHolder errorHolder = new ErrorHolder(); checker.check(new MountedNodeStore(mip.getMountByName("first"), mount), TreeFactory.createReadOnlyTree(mount.getRoot()).getChild("first"), errorHolder, context); errorHolder.end(); } }
@Test(expected = CommitFailedException.class) public void mountAndUniqueIndexes() throws Exception { NodeState root = INITIAL_CONTENT; // Add index definition NodeBuilder builder = root.builder(); NodeBuilder index = createIndexDefinition(builder.child(INDEX_DEFINITIONS_NAME), "foo", true, true, ImmutableSet.of("foo"), null); index.setProperty("entryCount", -1); NodeState before = builder.getNodeState(); MountInfoProvider mip = Mounts.newBuilder() .mount("foo", "/a") .build(); builder.child("a").setProperty("foo", "abc"); builder.child("b").setProperty("foo", Arrays.asList("abc", "def"), Type.STRINGS); NodeState after = builder.getNodeState(); EditorHook hook = new EditorHook( new IndexUpdateProvider(new PropertyIndexEditorProvider().with(mip))); // should throw hook.processCommit(before, after, CommitInfo.EMPTY); }
@Test public void deleteIncludingMount() throws Exception{ mip = Mounts.newBuilder() .mount("foo", "/content/remote").build(); initializeMounts(); LuceneIndexWriterFactory factory = newDirectoryFactory(); LuceneIndexWriter writer = factory.newInstance(defn, builder, true); writer.updateDocument("/content/remote/a", newDoc("/content/remote/a")); writer.updateDocument("/etc", newDoc("/etc")); writer.updateDocument("/content", newDoc("/content")); writer.close(0); assertEquals(1, numDocs(fooMount)); assertEquals(2, numDocs(defaultMount)); writer = factory.newInstance(defn, builder, true); writer.deleteDocuments("/content"); writer.close(0); assertEquals(0, numDocs(fooMount)); assertEquals(1, numDocs(defaultMount)); }
@Test(expected = IllegalRepositoryStateException.class) public void versionableNode() throws CommitFailedException { MemoryNodeStore root = new MemoryNodeStore(); MemoryNodeStore mount = new MemoryNodeStore(); // create a child node that is versionable // note that we won't cover all checks here, we are only interested in seeing that at least one check is triggered NodeBuilder rootBuilder = mount.getRoot().builder(); NodeBuilder childNode = rootBuilder.setChildNode("readOnly").setChildNode("second").setChildNode("third"); childNode.setProperty(JcrConstants.JCR_ISCHECKEDOUT, false); childNode.setProperty(PropertyStates.createProperty(JcrConstants.JCR_MIXINTYPES , Collections.singletonList(JcrConstants.MIX_VERSIONABLE), Type.NAMES)); mount.merge(rootBuilder, EmptyHook.INSTANCE, CommitInfo.EMPTY); MountInfoProvider mip = Mounts.newBuilder() .readOnlyMount("readOnly", "/readOnly") .build(); new CompositeNodeStore.Builder(mip, root) .addMount("readOnly", mount) .with(new NodeStoreChecksService(mip, Collections.singletonList(new NodeTypeMountedNodeStoreChecker(JcrConstants.MIX_VERSIONABLE, "test error")))) .build(); } }
@Test public void multiplexingWriter() throws Exception{ newLucenePropertyIndex("lucene", "foo"); MountInfoProvider mip = Mounts.newBuilder() .mount("foo", "/libs", "/apps").build(); EditorHook hook = new EditorHook( new IndexUpdateProvider( new LuceneIndexEditorProvider(null, new ExtractedTextCache(0, 0), null, mip))); NodeState indexed = hook.processCommit(EMPTY_NODE, builder.getNodeState(), CommitInfo.EMPTY); builder = indexed.builder(); NodeState before = indexed; builder.child("content").child("en").setProperty("foo", "bar"); builder.child("libs").child("install").setProperty("foo", "bar"); NodeState after = builder.getNodeState(); indexed = hook.processCommit(before, after, CommitInfo.EMPTY); builder = indexed.builder(); assertEquals(1, numDocs(mip.getMountByName("foo"))); assertEquals(1, numDocs(mip.getDefaultMount())); }
@Test public void contributingStoreReturnsInfinity() { MountInfoProvider mip = Mounts.newBuilder().readOnlyMount("libs", "/libs", "/libs1", "/libs2", "/libs3", "/libs4").build(); NodeStore globalStore = new MemoryNodeStore(); NodeStore libsStore = new MemoryNodeStore(); List<MountedNodeStore> mounts = Lists.newArrayList(); mounts.add(new MountedNodeStore(mip.getMountByName("libs"), libsStore)); CompositeNodeStore compositeNodeStore = new CompositeNodeStore(mip, globalStore, mounts); CompositeNodeStoreBuilder b = new CompositeNodeStoreBuilder(compositeNodeStore.ctx); TestingNodeState globalTestingNS = b.configureMount("/", 5); TestingNodeState libsTestingNS = b.configureMount("/libs", MAX_VALUE); CompositeNodeState mns = b.getNodeState(); assertEquals(MAX_VALUE, mns.getChildNodeCount(100)); assertEquals(5, globalTestingNS.fetchedChildren); assertEquals(0, libsTestingNS.fetchedChildren); globalTestingNS.fetchedChildren = 0; libsTestingNS.fetchedChildren = 0; assertEquals(MAX_VALUE, mns.builder().getChildNodeCount(100)); assertEquals(5, globalTestingNS.fetchedChildren); assertEquals(0, libsTestingNS.fetchedChildren); }
@Test(expected = IllegalRepositoryStateException.class) public void referenceableNodeIsDetected() throws CommitFailedException { MemoryNodeStore root = new MemoryNodeStore(); MemoryNodeStore mount = new MemoryNodeStore(); NodeBuilder builder = mount.getRoot().builder(); builder.child("first") .setProperty(PropertyStates.createProperty(JcrConstants.JCR_MIXINTYPES, Collections.singletonList(JcrConstants.MIX_REFERENCEABLE), Type.NAMES)) .setProperty(JcrConstants.JCR_UUID, UUID.randomUUID().toString()); mount.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY); MountInfoProvider mip = Mounts.newBuilder() .readOnlyMount("first", "/first") .build(); NodeTypeMountedNodeStoreChecker checker = new NodeTypeMountedNodeStoreChecker(JcrConstants.MIX_REFERENCEABLE, "test error"); Context context = checker.createContext(root, mip); ErrorHolder errorHolder = new ErrorHolder(); checker.check(new MountedNodeStore(mip.getMountByName("first"), mount), TreeFactory.createReadOnlyTree(mount.getRoot()).getChild("first"), errorHolder, context); errorHolder.end(); }