DotenvTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. <?php
  2. namespace Dotenv\Tests;
  3. use Dotenv\Dotenv;
  4. use Dotenv\Loader\Loader;
  5. use Dotenv\Repository\RepositoryBuilder;
  6. use Dotenv\Store\StoreBuilder;
  7. use PHPUnit\Framework\TestCase;
  8. class DotenvTest extends TestCase
  9. {
  10. /**
  11. * @var string
  12. */
  13. private $folder;
  14. /**
  15. * @before
  16. */
  17. public function setUpTest()
  18. {
  19. $this->folder = dirname(__DIR__).'/fixtures/env';
  20. }
  21. /**
  22. * @expectedException \Dotenv\Exception\InvalidPathException
  23. * @expectedExceptionMessage Unable to read any of the environment file(s) at
  24. */
  25. public function testDotenvThrowsExceptionIfUnableToLoadFile()
  26. {
  27. $dotenv = Dotenv::createImmutable(__DIR__);
  28. $dotenv->load();
  29. }
  30. /**
  31. * @expectedException \Dotenv\Exception\InvalidPathException
  32. * @expectedExceptionMessage Unable to read any of the environment file(s) at
  33. */
  34. public function testDotenvThrowsExceptionIfUnableToLoadFiles()
  35. {
  36. $dotenv = Dotenv::createImmutable([__DIR__, __DIR__.'/foo/bar']);
  37. $dotenv->load();
  38. }
  39. /**
  40. * @expectedException \Dotenv\Exception\InvalidPathException
  41. * @expectedExceptionMessage At least one environment file path must be provided.
  42. */
  43. public function testDotenvThrowsExceptionWhenNoFiles()
  44. {
  45. $dotenv = Dotenv::createImmutable([]);
  46. $dotenv->load();
  47. }
  48. public function testDotenvTriesPathsToLoad()
  49. {
  50. $dotenv = Dotenv::createImmutable([__DIR__, $this->folder]);
  51. self::assertCount(4, $dotenv->load());
  52. }
  53. public function testDotenvTriesPathsToSafeLoad()
  54. {
  55. $dotenv = Dotenv::createImmutable([__DIR__, $this->folder]);
  56. self::assertCount(4, $dotenv->safeLoad());
  57. }
  58. public function testDotenvSkipsLoadingIfFileIsMissing()
  59. {
  60. $dotenv = Dotenv::createImmutable(__DIR__);
  61. self::assertSame([], $dotenv->safeLoad());
  62. }
  63. public function testDotenvLoadsEnvironmentVars()
  64. {
  65. $dotenv = Dotenv::createImmutable($this->folder);
  66. self::assertSame(
  67. ['FOO' => 'bar', 'BAR' => 'baz', 'SPACED' => 'with spaces', 'NULL' => ''],
  68. $dotenv->load()
  69. );
  70. self::assertSame('bar', getenv('FOO'));
  71. self::assertSame('baz', getenv('BAR'));
  72. self::assertSame('with spaces', getenv('SPACED'));
  73. self::assertEmpty(getenv('NULL'));
  74. }
  75. public function testDotenvLoadsEnvironmentVarsMultipleWithShortCircuitMode()
  76. {
  77. $dotenv = Dotenv::createImmutable($this->folder, ['.env', 'example.env']);
  78. self::assertSame(
  79. ['FOO' => 'bar', 'BAR' => 'baz', 'SPACED' => 'with spaces', 'NULL' => ''],
  80. $dotenv->load()
  81. );
  82. }
  83. public function testDotenvLoadsEnvironmentVarsMultipleWithoutShortCircuitMode()
  84. {
  85. $dotenv = Dotenv::createImmutable($this->folder, ['.env', 'example.env'], false);
  86. self::assertSame(
  87. ['FOO' => 'bar', 'BAR' => 'baz', 'SPACED' => 'with spaces', 'NULL' => '', 'EG' => 'example'],
  88. $dotenv->load()
  89. );
  90. }
  91. public function testCommentedDotenvLoadsEnvironmentVars()
  92. {
  93. $dotenv = Dotenv::createImmutable($this->folder, 'commented.env');
  94. $dotenv->load();
  95. self::assertSame('bar', getenv('CFOO'));
  96. self::assertFalse(getenv('CBAR'));
  97. self::assertFalse(getenv('CZOO'));
  98. self::assertSame('with spaces', getenv('CSPACED'));
  99. self::assertSame('a value with a # character', getenv('CQUOTES'));
  100. self::assertSame('a value with a # character & a quote " character inside quotes', getenv('CQUOTESWITHQUOTE'));
  101. self::assertEmpty(getenv('CNULL'));
  102. self::assertEmpty(getenv('EMPTY'));
  103. self::assertEmpty(getenv('EMPTY2'));
  104. self::assertSame('foo', getenv('FOOO'));
  105. }
  106. public function testQuotedDotenvLoadsEnvironmentVars()
  107. {
  108. $dotenv = Dotenv::createImmutable($this->folder, 'quoted.env');
  109. $dotenv->load();
  110. self::assertSame('bar', getenv('QFOO'));
  111. self::assertSame('baz', getenv('QBAR'));
  112. self::assertSame('with spaces', getenv('QSPACED'));
  113. self::assertEmpty(getenv('QNULL'));
  114. self::assertSame('pgsql:host=localhost;dbname=test', getenv('QEQUALS'));
  115. self::assertSame('test some escaped characters like a quote (") or maybe a backslash (\\)', getenv('QESCAPED'));
  116. self::assertSame('iiiiviiiixiiiiviiii\\n', getenv('QSLASH'));
  117. self::assertSame('iiiiviiiixiiiiviiii\\\\n', getenv('SQSLASH'));
  118. }
  119. public function testLargeDotenvLoadsEnvironmentVars()
  120. {
  121. $dotenv = Dotenv::createImmutable($this->folder, 'large.env');
  122. $dotenv->load();
  123. self::assertNotEmpty(getenv('LARGE'));
  124. }
  125. public function testMultipleDotenvLoadsEnvironmentVars()
  126. {
  127. $dotenv = Dotenv::createImmutable($this->folder, 'multiple.env');
  128. $dotenv->load();
  129. self::assertSame('bar', getenv('MULTI1'));
  130. self::assertSame('foo', getenv('MULTI2'));
  131. }
  132. public function testExportedDotenvLoadsEnvironmentVars()
  133. {
  134. $dotenv = Dotenv::createImmutable($this->folder, 'exported.env');
  135. $dotenv->load();
  136. self::assertSame('bar', getenv('EFOO'));
  137. self::assertSame('baz', getenv('EBAR'));
  138. self::assertSame('with spaces', getenv('ESPACED'));
  139. self::assertEmpty(getenv('ENULL'));
  140. }
  141. public function testDotenvLoadsEnvGlobals()
  142. {
  143. $dotenv = Dotenv::createImmutable($this->folder);
  144. $dotenv->load();
  145. self::assertSame('bar', $_SERVER['FOO']);
  146. self::assertSame('baz', $_SERVER['BAR']);
  147. self::assertSame('with spaces', $_SERVER['SPACED']);
  148. self::assertEmpty($_SERVER['NULL']);
  149. }
  150. public function testDotenvLoadsServerGlobals()
  151. {
  152. $dotenv = Dotenv::createImmutable($this->folder);
  153. $dotenv->load();
  154. self::assertSame('bar', $_ENV['FOO']);
  155. self::assertSame('baz', $_ENV['BAR']);
  156. self::assertSame('with spaces', $_ENV['SPACED']);
  157. self::assertEmpty($_ENV['NULL']);
  158. }
  159. public function testDotenvNestedEnvironmentVars()
  160. {
  161. $dotenv = Dotenv::createImmutable($this->folder, 'nested.env');
  162. $dotenv->load();
  163. self::assertSame('{$NVAR1} {$NVAR2}', $_ENV['NVAR3']); // not resolved
  164. self::assertSame('Hello World!', $_ENV['NVAR4']);
  165. self::assertSame('$NVAR1 {NVAR2}', $_ENV['NVAR5']); // not resolved
  166. self::assertSame('Special Value', $_ENV['N.VAR6']); // new '.' (dot) in var name
  167. self::assertSame('Special Value', $_ENV['NVAR7']); // nested '.' (dot) variable
  168. self::assertSame('', $_ENV['NVAR8']); // nested variable is empty string
  169. self::assertSame('', $_ENV['NVAR9']); // nested variable is empty string
  170. self::assertSame('${NVAR888}', $_ENV['NVAR10']); // nested variable is not set
  171. self::assertSame('NVAR1', $_ENV['NVAR11']);
  172. self::assertSame('Hello', $_ENV['NVAR12']);
  173. self::assertSame('${${NVAR11}}', $_ENV['NVAR13']); // single quotes
  174. self::assertSame('${NVAR1} ${NVAR2}', $_ENV['NVAR14']); // single quotes
  175. self::assertSame('${NVAR1} ${NVAR2}', $_ENV['NVAR15']); // escaped
  176. }
  177. public function testDotenvNullFileArgumentUsesDefault()
  178. {
  179. $dotenv = Dotenv::createImmutable($this->folder, null);
  180. $dotenv->load();
  181. self::assertSame('bar', getenv('FOO'));
  182. }
  183. /**
  184. * The fixture data has whitespace between the key and in the value string.
  185. *
  186. * Test that these keys are trimmed down.
  187. */
  188. public function testDotenvTrimmedKeys()
  189. {
  190. $dotenv = Dotenv::createImmutable($this->folder, 'quoted.env');
  191. $dotenv->load();
  192. self::assertSame('no space', getenv('QWHITESPACE'));
  193. }
  194. public function testDotenvLoadDoesNotOverwriteEnv()
  195. {
  196. putenv('IMMUTABLE=true');
  197. $dotenv = Dotenv::createImmutable($this->folder, 'immutable.env');
  198. $dotenv->load();
  199. self::assertSame('true', getenv('IMMUTABLE'));
  200. }
  201. public function testDotenvLoadAfterOverload()
  202. {
  203. putenv('IMMUTABLE=true');
  204. $dotenv = Dotenv::createMutable($this->folder, 'immutable.env');
  205. $dotenv->load();
  206. self::assertSame('false', getenv('IMMUTABLE'));
  207. }
  208. public function testDotenvOverloadAfterLoad()
  209. {
  210. putenv('IMMUTABLE=true');
  211. $dotenv = Dotenv::createImmutable($this->folder, 'immutable.env');
  212. $dotenv->load();
  213. self::assertSame('true', getenv('IMMUTABLE'));
  214. }
  215. public function testDotenvOverloadDoesOverwriteEnv()
  216. {
  217. $dotenv = Dotenv::createMutable($this->folder, 'mutable.env');
  218. $dotenv->load();
  219. self::assertSame('true', getenv('MUTABLE'));
  220. }
  221. public function testDotenvAllowsSpecialCharacters()
  222. {
  223. $dotenv = Dotenv::createImmutable($this->folder, 'specialchars.env');
  224. $dotenv->load();
  225. self::assertSame('$a6^C7k%zs+e^.jvjXk', getenv('SPVAR1'));
  226. self::assertSame('?BUty3koaV3%GA*hMAwH}B', getenv('SPVAR2'));
  227. self::assertSame('jdgEB4{QgEC]HL))&GcXxokB+wqoN+j>xkV7K?m$r', getenv('SPVAR3'));
  228. self::assertSame('22222:22#2^{', getenv('SPVAR4'));
  229. self::assertSame('test some escaped characters like a quote " or maybe a backslash \\', getenv('SPVAR5'));
  230. self::assertSame('secret!@', getenv('SPVAR6'));
  231. self::assertSame('secret!@#', getenv('SPVAR7'));
  232. self::assertSame('secret!@#', getenv('SPVAR8'));
  233. }
  234. public function testMutlilineLoading()
  235. {
  236. $dotenv = Dotenv::createImmutable($this->folder, 'multiline.env');
  237. $dotenv->load();
  238. self::assertSame("test\n test\"test\"\n test", getenv('TEST'));
  239. self::assertSame("test\ntest", getenv('TEST_ND'));
  240. self::assertSame('test\\ntest', getenv('TEST_NS'));
  241. self::assertSame('https://vision.googleapis.com/v1/images:annotate?key=', getenv('TEST_EQD'));
  242. self::assertSame('https://vision.googleapis.com/v1/images:annotate?key=', getenv('TEST_EQS'));
  243. }
  244. public function testEmptyLoading()
  245. {
  246. $dotenv = Dotenv::createImmutable($this->folder, 'empty.env');
  247. self::assertSame(['EMPTY_VAR' => null], $dotenv->load());
  248. }
  249. public function testLegacyConstructor()
  250. {
  251. $loader = new Loader();
  252. $repository = RepositoryBuilder::create()->immutable()->make();
  253. $dotenv = new Dotenv($loader, $repository, [$this->folder.DIRECTORY_SEPARATOR.'.env']);
  254. self::assertSame([
  255. 'FOO' => 'bar',
  256. 'BAR' => 'baz',
  257. 'SPACED' => 'with spaces',
  258. 'NULL' => '',
  259. ], $dotenv->load());
  260. }
  261. public function testLatestConstructor()
  262. {
  263. $loader = new Loader();
  264. $repository = RepositoryBuilder::create()->immutable()->make();
  265. $store = StoreBuilder::create()->withPaths($this->folder)->make();
  266. $dotenv = new Dotenv($loader, $repository, $store);
  267. self::assertSame([
  268. 'FOO' => 'bar',
  269. 'BAR' => 'baz',
  270. 'SPACED' => 'with spaces',
  271. 'NULL' => '',
  272. ], $dotenv->load());
  273. }
  274. public function testDotenvParseExample1()
  275. {
  276. $output = Dotenv::parse(
  277. "BASE_DIR=\"/var/webroot/project-root\"\nCACHE_DIR=\"\${BASE_DIR}/cache\"\nTMP_DIR=\"\${BASE_DIR}/tmp\"\n"
  278. );
  279. self::assertSame($output, [
  280. 'BASE_DIR' => '/var/webroot/project-root',
  281. 'CACHE_DIR' => '/var/webroot/project-root/cache',
  282. 'TMP_DIR' => '/var/webroot/project-root/tmp',
  283. ]);
  284. }
  285. public function testDotenvParseExample2()
  286. {
  287. $output = Dotenv::parse("FOO=Bar\nBAZ=\"Hello \${FOO}\"");
  288. self::assertSame($output, ['FOO' => 'Bar', 'BAZ' => 'Hello Bar']);
  289. }
  290. public function testDotenvParseEmptyCase()
  291. {
  292. $output = Dotenv::parse('');
  293. self::assertSame($output, []);
  294. }
  295. }