1+ <?php namespace com \amazon \aws \lambda \unittest ;
2+
3+ use io \archive \zip \{ZipFile , ZipIterator };
4+ use io \streams \MemoryOutputStream ;
5+ use io \{File , Files , Folder , Path };
6+ use lang \Environment ;
7+ use test \verify \Runtime ;
8+ use test \{After , Assert , Test , Values };
9+ use util \cmd \Console ;
10+ use xp \lambda \{PackageLambda , Sources };
11+
12+ class PackagingTest {
13+ private $ archives = [], $ cleanup = [];
14+
15+ /** Creates a new temporary folder */
16+ private function tempDir (): Folder {
17+ $ this ->cleanup []= $ f = new Folder (Environment::tempDir (), uniqid ());
18+ $ f ->create ();
19+ return $ f ;
20+ }
21+
22+ /** @return void */
23+ private function removeDir (Folder $ folder ) {
24+ foreach ($ folder ->entries () as $ entry ) {
25+ switch ($ m = lstat ($ entry )['mode ' ] & 0170000 ) {
26+ case Sources::IS_LINK : unlink ($ entry ); break ;
27+ case Sources::IS_FILE : $ entry ->asFile ()->unlink (); break ;
28+ case Sources::IS_FOLDER : $ this ->removeDir ($ entry ->asFolder ()); break ;
29+ }
30+ }
31+ }
32+
33+ /** Creates files and directory from given definitions */
34+ private function create (array $ definitions , Folder $ folder = null ): Path {
35+ $ folder ?? $ folder = $ this ->tempDir ();
36+
37+ // Create sources from definitions
38+ foreach ($ definitions as $ name => $ definition ) {
39+ switch ($ definition [0 ]) {
40+ case Sources::IS_FILE :
41+ Files::write (new File ($ folder , $ name ), $ definition [1 ]);
42+ break ;
43+
44+ case Sources::IS_FOLDER :
45+ (new Folder ($ folder , $ name ))->create ($ definition [1 ]);
46+ break ;
47+
48+ case Sources::IS_LINK :
49+ symlink ($ definition [1 ], new Path ($ folder , $ name ));
50+ break ;
51+ }
52+ }
53+
54+ return new Path ($ folder );
55+ }
56+
57+ /** Creates package from given sources */
58+ private function package (Sources $ sources ): ZipIterator {
59+
60+ // Run packaging command
61+ $ target = new Path ($ this ->tempDir (), 'test.zip ' );
62+ $ out = Console::$ out ->stream ();
63+ Console::$ out ->redirect (new MemoryOutputStream ());
64+ try {
65+ $ cmd = new PackageLambda ($ target , $ sources );
66+ $ cmd ->run ();
67+ } finally {
68+ Console::$ out ->redirect ($ out );
69+ }
70+
71+ // Remember to close the archive
72+ $ this ->archives []= $ zip = ZipFile::open ($ target );
73+ return $ zip ->iterator ();
74+ }
75+
76+ #[After]
77+ private function cleanup () {
78+ foreach ($ this ->files as $ file ) {
79+ $ file ->close ();
80+ }
81+ foreach ($ this ->cleanup as $ folder ) {
82+ $ this ->removeDir ($ folder );
83+ }
84+ }
85+
86+ #[Test]
87+ public function single_file () {
88+ $ zip = $ this ->package (new Sources ($ this ->create (['file.txt ' => [Sources::IS_FILE , 'Test ' ]]), ['file.txt ' ]));
89+
90+ $ file = $ zip ->next ();
91+ Assert::equals ('file.txt ' , $ file ->getName ());
92+ Assert::equals (4 , $ file ->getSize ());
93+ Assert::false ($ zip ->hasNext ());
94+ }
95+
96+ #[Test]
97+ public function single_directory () {
98+ $ zip = $ this ->package (new Sources ($ this ->create (['src ' => [Sources::IS_FOLDER , 0755 ]]), ['src ' ]));
99+
100+ $ dir = $ zip ->next ();
101+ Assert::equals ('src/ ' , $ dir ->getName ());
102+ Assert::true ($ dir ->isDirectory ());
103+ Assert::false ($ zip ->hasNext ());
104+ }
105+
106+ #[Test]
107+ public function file_inside_directory () {
108+ $ path = $ this ->create ([
109+ 'src ' => [Sources::IS_FOLDER , 0755 ],
110+ 'src/file.txt ' => [Sources::IS_FILE , 'Test ' ]
111+ ]);
112+ $ zip = $ this ->package (new Sources ($ path , ['src ' ]));
113+
114+ $ dir = $ zip ->next ();
115+ Assert::equals ('src/ ' , $ dir ->getName ());
116+ Assert::true ($ dir ->isDirectory ());
117+
118+ $ file = $ zip ->next ();
119+ Assert::equals ('src/file.txt ' , $ file ->getName ());
120+ Assert::equals (4 , $ file ->getSize ());
121+
122+ Assert::false ($ zip ->hasNext ());
123+ }
124+
125+ #[Test, Runtime(os: 'Linux ' ), Values(['../../core ' , '%s/core ' ])]
126+ public function link_inside_directory ($ target ) {
127+ $ tempDir = $ this ->tempDir ();
128+
129+ $ link = sprintf ($ target , rtrim ($ tempDir ->getURI (), DIRECTORY_SEPARATOR ));
130+ $ path = $ this ->create ([
131+ 'core/ ' => [Sources::IS_FOLDER , 0755 ],
132+ 'core/composer.json ' => [Sources::IS_FILE , '{"require":{"php":">=7.0"}} ' ],
133+ 'project ' => [Sources::IS_FOLDER , 0755 ],
134+ 'project/src ' => [Sources::IS_FOLDER , 0755 ],
135+ 'project/src/file.txt ' => [Sources::IS_FILE , 'Test ' ],
136+ 'project/lib ' => [Sources::IS_FOLDER , 0755 ],
137+ 'project/lib/core ' => [Sources::IS_LINK , $ link ],
138+ ], $ tempDir );
139+ $ zip = $ this ->package (new Sources (new Path ($ path , 'project ' ), ['src ' , 'lib ' ]));
140+
141+ $ dir = $ zip ->next ();
142+ Assert::equals ('src/ ' , $ dir ->getName ());
143+ Assert::true ($ dir ->isDirectory ());
144+
145+ $ file = $ zip ->next ();
146+ Assert::equals ('src/file.txt ' , $ file ->getName ());
147+ Assert::equals (4 , $ file ->getSize ());
148+
149+ $ lib = $ zip ->next ();
150+ Assert::equals ('lib/ ' , $ lib ->getName ());
151+ Assert::true ($ lib ->isDirectory ());
152+
153+ $ core = $ zip ->next ();
154+ Assert::equals ('lib/core/ ' , $ core ->getName ());
155+ Assert::true ($ core ->isDirectory ());
156+
157+ $ composer = $ zip ->next ();
158+ Assert::equals ('lib/core/composer.json ' , $ composer ->getName ());
159+ Assert::equals (27 , $ composer ->getSize ());
160+
161+ Assert::false ($ zip ->hasNext ());
162+ }
163+
164+ #[Test, Runtime(os: 'Linux ' ), Values(['../../libs/inc.pth ' , '%s/libs/inc.pth ' ])]
165+ public function link_to_file ($ target ) {
166+ $ tempDir = $ this ->tempDir ();
167+
168+ $ link = sprintf ($ target , rtrim ($ tempDir ->getURI (), DIRECTORY_SEPARATOR ));
169+ $ path = $ this ->create ([
170+ 'libs/ ' => [Sources::IS_FOLDER , 0755 ],
171+ 'libs/inc.pth ' => [Sources::IS_FILE , 'src/main/php ' ],
172+ 'project ' => [Sources::IS_FOLDER , 0755 ],
173+ 'project/src ' => [Sources::IS_FOLDER , 0755 ],
174+ 'project/src/file.txt ' => [Sources::IS_FILE , 'Test ' ],
175+ 'project/lib ' => [Sources::IS_FOLDER , 0755 ],
176+ 'project/lib/inc.pth ' => [Sources::IS_LINK , $ link ],
177+ ], $ tempDir );
178+ $ zip = $ this ->package (new Sources (new Path ($ path , 'project ' ), ['src ' , 'lib ' ]));
179+
180+ $ dir = $ zip ->next ();
181+ Assert::equals ('src/ ' , $ dir ->getName ());
182+ Assert::true ($ dir ->isDirectory ());
183+
184+ $ file = $ zip ->next ();
185+ Assert::equals ('src/file.txt ' , $ file ->getName ());
186+ Assert::equals (4 , $ file ->getSize ());
187+
188+ $ lib = $ zip ->next ();
189+ Assert::equals ('lib/ ' , $ lib ->getName ());
190+ Assert::true ($ lib ->isDirectory ());
191+
192+ $ path = $ zip ->next ();
193+ Assert::equals ('lib/inc.pth ' , $ path ->getName ());
194+ Assert::equals (12 , $ path ->getSize ());
195+
196+ Assert::false ($ zip ->hasNext ());
197+ }
198+ }
0 commit comments