2828import org .apache .cloudstack .engine .subsystem .api .storage .SnapshotResult ;
2929import org .apache .cloudstack .engine .subsystem .api .storage .SnapshotService ;
3030import org .apache .cloudstack .framework .async .AsyncCallFuture ;
31+ import org .apache .cloudstack .context .CallContext ;
32+ import org .apache .cloudstack .engine .subsystem .api .storage .VolumeDataFactory ;
33+ import org .apache .cloudstack .engine .subsystem .api .storage .VolumeInfo ;
34+ import org .apache .cloudstack .storage .datastore .db .PrimaryDataStoreDao ;
3135import org .apache .cloudstack .storage .datastore .db .SnapshotDataStoreDao ;
3236import org .apache .cloudstack .storage .datastore .db .SnapshotDataStoreVO ;
37+ import org .apache .cloudstack .storage .datastore .db .StoragePoolVO ;
3338import org .junit .Assert ;
3439import org .junit .Test ;
3540import org .junit .runner .RunWith ;
4550import com .cloud .dc .dao .DataCenterDao ;
4651import com .cloud .event .ActionEventUtils ;
4752import com .cloud .exception .InvalidParameterValueException ;
53+ import com .cloud .hypervisor .Hypervisor .HypervisorType ;
4854import com .cloud .exception .PermissionDeniedException ;
4955import com .cloud .exception .ResourceUnavailableException ;
5056import com .cloud .org .Grouping ;
5157import com .cloud .storage .DataStoreRole ;
58+ import com .cloud .storage .ScopeType ;
5259import com .cloud .storage .Snapshot ;
5360import com .cloud .storage .SnapshotVO ;
5461import com .cloud .storage .VolumeVO ;
5966import com .cloud .user .AccountManager ;
6067import com .cloud .user .AccountVO ;
6168import com .cloud .user .ResourceLimitService ;
69+ import com .cloud .user .User ;
6270import com .cloud .user .dao .AccountDao ;
6371import com .cloud .utils .Pair ;
72+ import com .cloud .vm .dao .UserVmDao ;
6473
6574@ RunWith (MockitoJUnitRunner .class )
6675public class SnapshotManagerImplTest {
@@ -86,9 +95,44 @@ public class SnapshotManagerImplTest {
8695 SnapshotZoneDao snapshotZoneDao ;
8796 @ Mock
8897 VolumeDao volumeDao ;
98+ @ Mock
99+ PrimaryDataStoreDao primaryDataStoreDao ;
100+ @ Mock
101+ VolumeDataFactory volFactory ;
102+ @ Mock
103+ UserVmDao userVmDao ;
89104 @ InjectMocks
90105 SnapshotManagerImpl snapshotManager = new SnapshotManagerImpl ();
91106
107+ @ Test
108+ public void testAllocSnapshotRejectsDuplicateNameForVolume () {
109+ long volumeId = 1L ;
110+ CallContext .register (Mockito .mock (User .class ), Mockito .mock (Account .class ));
111+ try {
112+ VolumeInfo volume = Mockito .mock (VolumeInfo .class );
113+ Mockito .when (volFactory .getVolume (volumeId )).thenReturn (volume );
114+ DataStore dataStore = Mockito .mock (DataStore .class );
115+ Mockito .when (volume .getDataStore ()).thenReturn (dataStore );
116+ Mockito .when (dataStore .getId ()).thenReturn (10L );
117+ StoragePoolVO pool = Mockito .mock (StoragePoolVO .class );
118+ Mockito .when (primaryDataStoreDao .findById (10L )).thenReturn (pool );
119+ Mockito .when (pool .getScope ()).thenReturn (ScopeType .ZONE );
120+ Mockito .when (pool .getHypervisor ()).thenReturn (HypervisorType .None );
121+ Mockito .when (volume .getInstanceId ()).thenReturn (null );
122+ Mockito .when (volume .getAccountId ()).thenReturn (2L );
123+
124+ SnapshotVO existing = Mockito .mock (SnapshotVO .class );
125+ Mockito .when (existing .getName ()).thenReturn ("dup" );
126+ Mockito .when (snapshotDao .listByStatusNotIn (volumeId , Snapshot .State .Destroyed , Snapshot .State .Error ))
127+ .thenReturn (List .of (existing ));
128+
129+ Assert .assertThrows (InvalidParameterValueException .class , () ->
130+ snapshotManager .allocSnapshot (volumeId , Snapshot .MANUAL_POLICY_ID , "dup" , null ));
131+ } finally {
132+ CallContext .unregister ();
133+ }
134+ }
135+
92136 @ Test
93137 public void testGetSnapshotZoneImageStoreValid () {
94138 final long snapshotId = 1L ;
0 commit comments