1 /* 2 * Copyright (C) 2009, Google Inc. 3 * Copyright (C) 2009, Robin Rosenberg <robin.rosenberg@dewire.com> 4 * Copyright (C) 2009, Yann Simon <yann.simon.fr@gmail.com> and others 5 * 6 * This program and the accompanying materials are made available under the 7 * terms of the Eclipse Distribution License v. 1.0 which is available at 8 * https://www.eclipse.org/org/documents/edl-v10.php. 9 * 10 * SPDX-License-Identifier: BSD-3-Clause 11 */ 12 13 package org.eclipse.jgit.junit; 14 15 import java.io.File; 16 import java.io.IOException; 17 import java.lang.reflect.Field; 18 import java.text.DateFormat; 19 import java.text.SimpleDateFormat; 20 import java.time.Duration; 21 import java.util.HashMap; 22 import java.util.Locale; 23 import java.util.Map; 24 import java.util.TimeZone; 25 import java.util.concurrent.TimeUnit; 26 27 import org.eclipse.jgit.errors.ConfigInvalidException; 28 import org.eclipse.jgit.lib.Config; 29 import org.eclipse.jgit.lib.Constants; 30 import org.eclipse.jgit.lib.StoredConfig; 31 import org.eclipse.jgit.storage.file.FileBasedConfig; 32 import org.eclipse.jgit.util.FS; 33 import org.eclipse.jgit.util.SystemReader; 34 import org.eclipse.jgit.util.time.MonotonicClock; 35 import org.eclipse.jgit.util.time.ProposedTimestamp; 36 37 /** 38 * Mock {@link org.eclipse.jgit.util.SystemReader} for tests. 39 */ 40 public class MockSystemReader extends SystemReader { 41 private static final class MockConfig extends FileBasedConfig { MockConfig(File cfgLocation, FS fs)42 private MockConfig(File cfgLocation, FS fs) { 43 super(cfgLocation, fs); 44 } 45 46 @Override load()47 public void load() throws IOException, ConfigInvalidException { 48 // Do nothing 49 } 50 51 @Override save()52 public void save() throws IOException { 53 // Do nothing 54 } 55 56 @Override isOutdated()57 public boolean isOutdated() { 58 return false; 59 } 60 61 @Override toString()62 public String toString() { 63 return "MockConfig"; 64 } 65 } 66 67 long now = 1250379778668L; // Sat Aug 15 20:12:58 GMT-03:30 2009 68 69 final Map<String, String> values = new HashMap<>(); 70 71 private FileBasedConfig userGitConfig; 72 73 private FileBasedConfig jgitConfig; 74 75 FileBasedConfig systemGitConfig; 76 77 /** 78 * Set the user-level git config 79 * 80 * @param userGitConfig 81 * set another user-level git config 82 * @return the old user-level git config 83 */ setUserGitConfig(FileBasedConfig userGitConfig)84 public FileBasedConfig setUserGitConfig(FileBasedConfig userGitConfig) { 85 FileBasedConfig old = this.userGitConfig; 86 this.userGitConfig = userGitConfig; 87 return old; 88 } 89 90 /** 91 * Set the jgit config stored at $XDG_CONFIG_HOME/jgit/config 92 * 93 * @param jgitConfig 94 * set the jgit configuration 95 */ setJGitConfig(FileBasedConfig jgitConfig)96 public void setJGitConfig(FileBasedConfig jgitConfig) { 97 this.jgitConfig = jgitConfig; 98 } 99 100 /** 101 * Set the system-level git config 102 * 103 * @param systemGitConfig 104 * the new system-level git config 105 * @return the old system-level config 106 */ setSystemGitConfig(FileBasedConfig systemGitConfig)107 public FileBasedConfig setSystemGitConfig(FileBasedConfig systemGitConfig) { 108 FileBasedConfig old = this.systemGitConfig; 109 this.systemGitConfig = systemGitConfig; 110 return old; 111 } 112 113 /** 114 * Constructor for <code>MockSystemReader</code> 115 */ MockSystemReader()116 public MockSystemReader() { 117 init(Constants.OS_USER_NAME_KEY); 118 init(Constants.GIT_AUTHOR_NAME_KEY); 119 init(Constants.GIT_AUTHOR_EMAIL_KEY); 120 init(Constants.GIT_COMMITTER_NAME_KEY); 121 init(Constants.GIT_COMMITTER_EMAIL_KEY); 122 setProperty(Constants.OS_USER_DIR, "."); 123 userGitConfig = new MockConfig(null, null); 124 jgitConfig = new MockConfig(null, null); 125 systemGitConfig = new MockConfig(null, null); 126 setCurrentPlatform(); 127 } 128 init(String n)129 private void init(String n) { 130 setProperty(n, n); 131 } 132 133 /** 134 * Clear properties 135 */ clearProperties()136 public void clearProperties() { 137 values.clear(); 138 } 139 140 /** 141 * Set a property 142 * 143 * @param key 144 * @param value 145 */ setProperty(String key, String value)146 public void setProperty(String key, String value) { 147 values.put(key, value); 148 } 149 150 /** {@inheritDoc} */ 151 @Override getenv(String variable)152 public String getenv(String variable) { 153 return values.get(variable); 154 } 155 156 /** {@inheritDoc} */ 157 @Override getProperty(String key)158 public String getProperty(String key) { 159 return values.get(key); 160 } 161 162 /** {@inheritDoc} */ 163 @Override openUserConfig(Config parent, FS fs)164 public FileBasedConfig openUserConfig(Config parent, FS fs) { 165 assert parent == null || parent == systemGitConfig; 166 return userGitConfig; 167 } 168 169 /** {@inheritDoc} */ 170 @Override openSystemConfig(Config parent, FS fs)171 public FileBasedConfig openSystemConfig(Config parent, FS fs) { 172 assert parent == null; 173 return systemGitConfig; 174 } 175 176 @Override getUserConfig()177 public StoredConfig getUserConfig() 178 throws IOException, ConfigInvalidException { 179 return userGitConfig; 180 } 181 182 @Override getJGitConfig()183 public FileBasedConfig getJGitConfig() { 184 return jgitConfig; 185 } 186 187 @Override getSystemConfig()188 public StoredConfig getSystemConfig() 189 throws IOException, ConfigInvalidException { 190 return systemGitConfig; 191 } 192 193 /** {@inheritDoc} */ 194 @Override getHostname()195 public String getHostname() { 196 return "fake.host.example.com"; 197 } 198 199 /** {@inheritDoc} */ 200 @Override getCurrentTime()201 public long getCurrentTime() { 202 return now; 203 } 204 205 /** {@inheritDoc} */ 206 @Override getClock()207 public MonotonicClock getClock() { 208 return () -> { 209 long t = getCurrentTime(); 210 return new ProposedTimestamp() { 211 212 @Override 213 public long read(TimeUnit unit) { 214 return unit.convert(t, TimeUnit.MILLISECONDS); 215 } 216 217 @Override 218 public void blockUntil(Duration maxWait) { 219 // Do not wait. 220 } 221 }; 222 }; 223 } 224 225 /** 226 * Adjusts the current time in seconds. 227 * 228 * @param secDelta 229 * number of seconds to add to the current time. 230 * @since 4.2 231 */ 232 public void tick(int secDelta) { 233 now += secDelta * 1000L; 234 } 235 236 /** {@inheritDoc} */ 237 @Override 238 public int getTimezone(long when) { 239 return getTimeZone().getOffset(when) / (60 * 1000); 240 } 241 242 /** {@inheritDoc} */ 243 @Override 244 public TimeZone getTimeZone() { 245 return TimeZone.getTimeZone("GMT-03:30"); 246 } 247 248 /** {@inheritDoc} */ 249 @Override 250 public Locale getLocale() { 251 return Locale.US; 252 } 253 254 /** {@inheritDoc} */ 255 @Override 256 public SimpleDateFormat getSimpleDateFormat(String pattern) { 257 return new SimpleDateFormat(pattern, getLocale()); 258 } 259 260 /** {@inheritDoc} */ 261 @Override 262 public DateFormat getDateTimeInstance(int dateStyle, int timeStyle) { 263 return DateFormat 264 .getDateTimeInstance(dateStyle, timeStyle, getLocale()); 265 } 266 267 /** 268 * Assign some properties for the currently executing platform 269 */ 270 public void setCurrentPlatform() { 271 resetOsNames(); 272 setProperty("os.name", System.getProperty("os.name")); 273 setProperty("file.separator", System.getProperty("file.separator")); 274 setProperty("path.separator", System.getProperty("path.separator")); 275 setProperty("line.separator", System.getProperty("line.separator")); 276 } 277 278 /** 279 * Emulate Windows 280 */ 281 public void setWindows() { 282 resetOsNames(); 283 setProperty("os.name", "Windows"); 284 setProperty("file.separator", "\\"); 285 setProperty("path.separator", ";"); 286 setProperty("line.separator", "\r\n"); 287 setPlatformChecker(); 288 } 289 290 /** 291 * Emulate Unix 292 */ 293 public void setUnix() { 294 resetOsNames(); 295 setProperty("os.name", "*nix"); // Essentially anything but Windows 296 setProperty("file.separator", "/"); 297 setProperty("path.separator", ":"); 298 setProperty("line.separator", "\n"); 299 setPlatformChecker(); 300 } 301 302 private void resetOsNames() { 303 Field field; 304 try { 305 field = SystemReader.class.getDeclaredField("isWindows"); 306 field.setAccessible(true); 307 field.set(null, null); 308 field = SystemReader.class.getDeclaredField("isMacOS"); 309 field.setAccessible(true); 310 field.set(null, null); 311 } catch (Exception e) { 312 e.printStackTrace(); 313 } 314 } 315 316 @Override 317 public String toString() { 318 return "MockSystemReader"; 319 } 320 321 @Override 322 public FileBasedConfig openJGitConfig(Config parent, FS fs) { 323 return jgitConfig; 324 } 325 326 } 327