Skip to main content
summaryrefslogtreecommitdiffstats
blob: 68075497c15cd4e459e897da33630de8ce8f9b37 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
 * Copyright (c) 2010-2013 Eike Stepper (Berlin, Germany) and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Pascal Lehmann - initial API and implementation
 *    Eike Stepper - maintenance
 */
package org.eclipse.emf.cdo.tests.bugzilla;

import org.eclipse.emf.cdo.common.branch.CDOBranch;
import org.eclipse.emf.cdo.common.commit.CDOChangeSetData;
import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion;
import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.server.IRepository;
import org.eclipse.emf.cdo.session.CDOSession;
import org.eclipse.emf.cdo.tests.AbstractCDOTest;
import org.eclipse.emf.cdo.tests.config.IRepositoryConfig;
import org.eclipse.emf.cdo.tests.model4.ContainedElementNoOpposite;
import org.eclipse.emf.cdo.tests.model4.GenRefMultiContained;
import org.eclipse.emf.cdo.transaction.CDOTransaction;
import org.eclipse.emf.cdo.util.CommitException;
import org.eclipse.emf.cdo.view.CDOAdapterPolicy;

import org.eclipse.emf.spi.cdo.DefaultCDOMerger;

import java.util.Map;

/**
 * List index problem during merge can cause a StaleReference in database even with XRef checking enabled.
 * <p>
 * See bug 326518
 *
 * @author Pascal Lehmann
 */
public class Bugzilla_326518_Test extends AbstractCDOTest
{
  @Override
  public synchronized Map<String, Object> getTestProperties()
  {
    Map<String, Object> map = super.getTestProperties();
    map.put(IRepository.Props.ENSURE_REFERENTIAL_INTEGRITY, "true");
    return map;
  }

  @Requires(IRepositoryConfig.CAPABILITY_BRANCHING)
  public void testIndexBranchMerge() throws Exception
  {
    skipStoreWithoutQueryXRefs();

    // setup transaction.
    final CDOSession session = openSession();
    final CDOTransaction transaction1 = session.openTransaction();
    transaction1.options().addChangeSubscriptionPolicy(CDOAdapterPolicy.ALL);

    // create resource, and container using transaction 1.
    final CDOResource resource = transaction1.createResource(getResourcePath("/test1"));
    GenRefMultiContained container = getModel4Factory().createGenRefMultiContained();
    resource.getContents().add(container);
    ContainedElementNoOpposite element1 = getModel4Factory().createContainedElementNoOpposite();
    ContainedElementNoOpposite element2 = getModel4Factory().createContainedElementNoOpposite();
    container.getElements().add(element1);
    container.getElements().add(element2);

    transaction1.commit();
    sleep(1000L);

    // setup another branch.
    final CDOBranch branch2 = transaction1.getBranch().createBranch("branch2");
    final CDOTransaction transaction2 = session.openTransaction(branch2);

    CDOResource branchResource = transaction2.getObject(resource);
    assertNotSame(null, branchResource);
    GenRefMultiContained otherContainer = (GenRefMultiContained)branchResource.getContents().get(0);
    assertNotSame(null, otherContainer);

    // detach the first element on branch.
    otherContainer.getElements().remove(0);
    // add a new element on branch at index0.
    otherContainer.getElements().add(0, getModel4Factory().createContainedElementNoOpposite());

    transaction2.commit();
    assertEquals(false, transaction2.isDirty());

    // detach the second element on main.
    container.getElements().remove(1);
    // add a new element on main at index0.
    container.getElements().add(0, getModel4Factory().createContainedElementNoOpposite());

    transaction1.commit();
    assertEquals(false, transaction1.isDirty());

    // merge the other branch to main.
    sleep(1000L);
    CDOChangeSetData changes = transaction1.merge(transaction2.getBranch().getHead(),
        new DefaultCDOMerger.PerFeature.ManyValued());

    printChangeSetData(changes);

    try
    {
      transaction1.commit();
    }
    catch (CommitException expected)
    {
      fail("No CommitException expected");
    }

    // access the container's elements.
    for (Object object : container.getElements()) // <-- will cause an ObjectNotFoundException.
    {
      System.out.println(object);
    }
  }

  public static void printChangeSetData(CDOChangeSetData changes)
  {
    StringBuilder sb = new StringBuilder();
    sb.append("## ChangeSet:\n");
    sb.append(" * New objects: ").append(changes.getNewObjects().size()).append("\n");
    for (CDOIDAndVersion idVersion : changes.getNewObjects())
    {
      sb.append("   - ").append(idVersion).append("\n");
    }

    sb.append(" * Changed objects: ").append(changes.getChangedObjects().size()).append("\n");
    for (CDORevisionKey revKey : changes.getChangedObjects())
    {
      sb.append("   - ").append(revKey).append("\n");
    }

    sb.append(" * Detached objects: ").append(changes.getNewObjects().size()).append("\n");
    for (CDOIDAndVersion idVersion : changes.getNewObjects())
    {
      sb.append("   - ").append(idVersion).append("\n");
    }

    System.out.println(sb);
  }
}

Back to the top