Asserting the Output of Complex Arrays in PHPUnit/PHPStorm

In unit testing, have you ever had assert a really complex array that you didn’t really want to generate the whole expected array yourself? Such as:

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
array (
  0 => 
  array (
    0 => 'var 0-0',
    1 => 'var 0-1',
    2 => 'var 0-2',
    3 => 'var 0-3',
    4 => 'var 0-4',
    5 => 'var 0-5',
    6 => 'var 0-6',
    7 => 'var 0-7',
    8 => 'var 0-8',
    9 => 'var 0-9',
  ),
  1 => 
  array (
    0 => 'var 1-0',
    1 => 'var 1-1',
    2 => 'var 1-2',
    3 => 'var 1-3',
    4 => 'var 1-4',
    5 => 'var 1-5',
    6 => 'var 1-6',
    7 => 'var 1-7',
    8 => 'var 1-8',
    9 => 'var 1-9',
  ),
  2 => 
  array (
    0 => 'var 2-0',
    1 => 'var 2-1',
    2 => 'var 2-2',
    3 => 'var 2-3',
    4 => 'var 2-4',
    5 => 'var 2-5',
    6 => 'var 2-6',
    7 => 'var 2-7',
    8 => 'var 2-8',
    9 => 'var 2-9',
  ),
  3 => 
  array (
    0 => 'var 3-0',
    1 => 'var 3-1',
    2 => 'var 3-2',
    3 => 'var 3-3',
    4 => 'var 3-4',
    5 => 'var 3-5',
    6 => 'var 3-6',
    7 => 'var 3-7',
    8 => 'var 3-8',
    9 => 'var 3-9',
  ),
  4 => 
  array (
    0 => 'var 4-0',
    1 => 'var 4-1',
    2 => 'var 4-2',
    3 => 'var 4-3',
    4 => 'var 4-4',
    5 => 'var 4-5',
    6 => 'var 4-6',
    7 => 'var 4-7',
    8 => 'var 4-8',
    9 => 'var 4-9',
  ),
  5 => 
  array (
    0 => 'var 5-0',
    1 => 'var 5-1',
    2 => 'var 5-2',
    3 => 'var 5-3',
    4 => 'var 5-4',
    5 => 'var 5-5',
    6 => 'var 5-6',
    7 => 'var 5-7',
    8 => 'var 5-8',
    9 => 'var 5-9',
  ),
  6 => 
  array (
    0 => 'var 6-0',
    1 => 'var 6-1',
    2 => 'var 6-2',
    3 => 'var 6-3',
    4 => 'var 6-4',
    5 => 'var 6-5',
    6 => 'var 6-6',
    7 => 'var 6-7',
    8 => 'var 6-8',
    9 => 'var 6-9',
  ),
  7 => 
  array (
    0 => 'var 7-0',
    1 => 'var 7-1',
    2 => 'var 7-2',
    3 => 'var 7-3',
    4 => 'var 7-4',
    5 => 'var 7-5',
    6 => 'var 7-6',
    7 => 'var 7-7',
    8 => 'var 7-8',
    9 => 'var 7-9',
  ),
  8 => 
  array (
    0 => 'var 8-0',
    1 => 'var 8-1',
    2 => 'var 8-2',
    3 => 'var 8-3',
    4 => 'var 8-4',
    5 => 'var 8-5',
    6 => 'var 8-6',
    7 => 'var 8-7',
    8 => 'var 8-8',
    9 => 'var 8-9',
  ),
  9 => 
  array (
    0 => 'var 9-0',
    1 => 'var 9-1',
    2 => 'var 9-2',
    3 => 'var 9-3',
    4 => 'var 9-4',
    5 => 'var 9-5',
    6 => 'var 9-6',
    7 => 'var 9-7',
    8 => 'var 9-8',
    9 => 'var 9-9',
  ),
  10 => 
  array (
    0 => 'var 10-0',
    1 => 'var 10-1',
    2 => 'var 10-2',
    3 => 'var 10-3',
    4 => 'var 10-4',
    5 => 'var 10-5',
    6 => 'var 10-6',
    7 => 'var 10-7',
    8 => 'var 10-8',
    9 => 'var 10-9',
  )

(I don’t want to type that up by hand!)

Well, guess what? You can be lazy about it… Simply use var_export and php will generate all the code for you to straight copy and paste.

1
var_export($complexObj);

**DISCLAIMER WARNING** This is generally a VERY bad practice. You are always suppose to create the assertions independently from what the output generates. It will be very easy to just copy and paste a mistake in the output that is not correct. Be sure if you do this that you look very carefully at the output and make sure it is exactly what it is supposed to be.

Lessons Learned in VPN Networking Domain Controllers

I had to setup a 2nd domain controller at an offsite location this past week. I don’t have any good VPN-ing routing equipment so I was just going to use OpenVPN to create a tunnel between the two sites. I set up OpenVPN to work with site-to-site routing and everything seemed to work… I could browse the shares from both sides, everyone was happy and could ping each other. I was even able to successfully install the 2nd domain controller and join the Windows domain. But then, I started getting all these random issues:

I spent lots of time troubleshooting it and I realized the issue. I set up the 2 OpenVPN servers to Masquerade NAT between the 2 subnets so all the traffic looked like it was coming from the VPN server itself. All the RPC calls were failing presumably because the domain controller was trying to open ports to communicate on. Anyways, I fixed that by making the openVPN server properly route and then DFSR was able to properly sync and replicate the two domain controllers. Moral of the story – make sure you set up proper routing and not NAT between domain controllers!

If you were able to get DCs working using masquerading NAT, please let me know. I’d be interested if that was possible.

Removing old Linux Kernels In Ubuntu

Ever get this on linux?

$ df -h /boot/
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 228M 228M 0M 100% /boot

Looks like ubuntu has been updating the kernels without cleaning itself up. Bad ubuntu! And it is terrible that the default boot partition is only 230MB. A quick google search gives me this one-liner:

$ dpkg -l linux-* | awk '/^ii/{ print $2}' | grep -v -e `uname -r | cut -f1,2 -d"-"` | grep -e [0-9] | xargs sudo apt-get -y purge

Thanks tuxtweats! http://tuxtweaks.com/2010/10/remove-old-kernels-in-ubuntu-with-one-command/

Troubleshooting Windows Automatically Turning On At Night

Do you ever put your computer to sleep or hibernate only to find it mysteriously staring at you the next morning awake?? That certainly disturbed me and I tried many things to stop my computer from being a zombie and eating brains in the middle of the night. :) Here’s the steps to troubleshoot and nail it on the head exactly what is happening.

Modern computer BIOSes have a host of functions for waking up the computer when it is off. Among them are the Real Time Clock (RTC) alarm that can wake up the computer on a scheduled basis (wiki), Wake On LAN (WOL) which can wakeup based on a special packet (wiki), device wake-up, and of course, the old fashion power button. Windows has a few programs that allows you to control the different features. For device wake-up, you can follow the instructions here. The post below is focused on RTC alarm which was the issue I was having.

If you are interested in killing this behavior all together and do not want to bother with everything else, simply navigate to Control Panel -> Search for “Power Options” -> On the left sidebar, “Change when the computer sleeps” -> “Change Advanced power settings”. You will see the screen below. Simply disable “Allow Wake Timers” and your computer will never wake up again by the timer when you put it to sleep.

I

If you are interested like me to figure out what exactly is causing the computer to wakeup, we can dive deeper into the power management system. Open a cmd prompt as administrator.

1
2
3
4
5
C:\Windows\system32>powercfg -waketimers
Timer set by [PROCESS] \Device\HarddiskVolume4\Windows\System32\services.exe exp
ires at 2:59:29 AM on 3/16/2013.
Reason: Windows will execute 'NT TASK\Microsoft\Windows\TaskScheduler\Regular
Maintenance' scheduled task that requested waking the computer.

We can see it is a scheduled task that is causing the system to wakeup at 2:59 in the morning. I’m on Windows 8, I believe the name might be different for previous versions, but you can go to Control Panel -> Search for “Scheduled” -> Scheduled Tasks. Look for the task listed above, in my case it was “Regular Maintenance”. Open that task and go to the “Conditions” tab and deselect “Wake the computer to run this task”.

After disabling that, check back with your wake timers and you should see the following:

C:\Windows\system32>powercfg -waketimers
There are no active wake timers in the system.

Now you can still have wakeup timers that go off when you want them while not having the daily 3AM alarm go off. :)

Achieving Fastest Intel Turboboost Speeds

I recently upgraded my desktop to a sweet i7-3770. :) I noticed though through Intel’s turboboost monitoring utility that I was only getting 3.7Ghz turboboost speeds.

3-4coreTurbo

If we look on Intel’s website (http://www.intel.com/support/processors/corei7/sb/CS-032279.htm) about the turboboost speeds of our system, we find:

Processor i7-3770 – 3.40 – GHz
Processor Cores Quad-core
Active Cores 4C 3C 2C 1C
Max Intel® Turbo Boost Bin Upside 3 4 5 5
Max Intel® Turbo Boost Frequency 3.7 3.8 3.9 3.9

So what that is saying is that at single or duel core load, the max speed is 3.9Ghz, at triple core load, the max should be 3.8Ghz, and at all full quad core load, the max speed is 3.7Ghz.

Odd thing for me is that I was never able to see the 3.9 or even the 3.8Ghz speed… I thought that perhaps Windows 8 always used all 4 cores, even some posts on the internet suggested that.

But I dug further and I found on wiki:

When the operating system instructed one of the active cores to enter C3 sleep state using the Advanced Configuration and Power Interface (ACPI), the other active core(s) dynamically accelerated to a higher frequency.

I realized that you need to make sure you have the ACPI C3 state option enabled in your BIOS. Some users who are looking to make their i7 perform the highest by disabling power saving features may actually be disabling the highest speeds for single core operations. I enabled this and now I get 3.9Ghz speeds:

1-2coreTurbo

 

Moral of the story – don’t disable ACPI to try to gain faster speeds, you might lose single/duel core turboboost!

PHPUnit Mocking

Mocking is great for very lean unit tests. It allows you to setup a repeatable scenario to test as many of the states of a unit as you want. In general, I want to be testing only a single method or a single class. If you’re testing more than this, you’re not writing unit tests – you’re writing integration tests! A good measure on if you are writing proper unit tests would be to change something in the code to make a test fail. If you end up with a cascade of tests fail, you have integration tests, not unit tests!

So in unit testing, you want to be able to isolate a single unit and manipulate the inputs to cover all types of conditions and verify the validity of the outputs to those conditions. I like to think of it like an algebraic inequality problem. You always check your boundaries and then a value within the different boundary regions. Think of it similarly with unit testing.

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
// Calculator.php
<?php
class Calculator {
    public getNumberFromUserInput() {
        // complicated function to get number from user input 
    }
 
    public divideBy($num2) {
        return $this->getNumberFromUserInput()/$num2;
    }
}
 
// CalculatorTest.php
<?php
 
include_once("Calculator.php");
 
class CalculatorTest extends \PHPUnit_Framework_TestCase {
    public function testDivideByPositiveNumber() {
        $calcMock=$this->getMock('\Calculator',array('getNumberFromUserInput'));
        $calcMock->expects($this->once())
            ->method('getNumberFromUserInput')
            ->will($this->returnValue(10));
        $this->assertEquals(5,$calcMock->divideBy(2));
    }
 
    public function testDivideByZero() {
        $calcMock=$this->getMock('\Calculator',array('getNumberFromUserInput'));
        $calcMock->expects($this->once())
            ->method('getNumberFromUserInput')
            ->will($this->returnValue(10));
        $this->assertEquals(NAN, $calcMock->divideBy(0));
 
    }
 
    public function testDivideByNegativeNumber() {
        $calcMock=$this->getMock('\Calculator',array('getNumberFromUserInput'));
        $calcMock->expects($this->once())
            ->method('getNumberFromUserInput')
            ->will($this->returnValue(10));
        $this->assertEquals(-2,$calcMock->divideBy(-5));
 
    }
}

As you can see with the example, sometimes inputs and outputs of functions are not always so straight-forward. While we can have our standard input and output passed from the method parameters and the return value, more often than not, inputs and outputs are received and sent by calling other functions. With mocking though, this is no issue. We can mock any function and  define exactly what it should return. We can also test and verify that the function was called.

Let’s break down the example.

1
$calcMock=$this->getMock('\Calculator',array('getNumberFromUserInput'));

We are creating a new Calculator mock. The first parameter tells phpunit what class to mock, the  2nd parameter tells phpunit to only mock the ‘getNumberFromUserInput’ function and not anything else. We need to use the real divideBy() function to test that. getMock() has a lot of useful options, refer to the api or Mark Mzyk’s blog post I found on the getMock method signatures.

The next line(s) set up the mocked function.

1
2
3
$calcMock->expects($this->once())
            ->method('getNumberFromUserInput')
            ->will($this->returnValue(10));

Line 1: We are saying here that we expect this method to be called once. If it is called less or more than once, we will get an exception.

Line 2: The method name we are mocking out.

Line 3: The return value of the mocked out function. You can also throw exceptions, return back one of the arguments unmodified, or even call another callback function. The code for that is $this->throwException(new Exception()), $this->returnArgument($ArgumentNumber) and $this->returnCallback($callbackMethod) respectively. With the callback, all the parameters you pass to the mock will be passed to the callback.

Anyways, back to our example, I ran the tests and we see at our 0 boundary that we get behavior that we were not expecting and our tests fail.

1
PHPUnit_Framework_Error_Warning : Division by zero

Let’s fix that up.

1
2
3
4
5
6
7
8
9
10
class Calculator {
public function getNumberFromUserInput() {
// complicated function to get number from user input
}
 
public function divideBy($num2) {
if ($num2 == 0) return NAN;
return $this->getNumberFromUserInput()/$num2;
}
}

A few more failures…

PHPUnit_Framework_ExpectationFailedException : Expectation failed for method name is equal to  when invoked 1 time(s).
Method was expected to be called 1 times, actually called 0 times.

And finally…

1
2
3
4
5
6
7
public function testDivideByZero() {
$calcMock=$this->getMock('\Calculator',array('getNumberFromUserInput'));
$calcMock->expects($this->never())
->method('getNumberFromUserInput')
->will($this->returnValue(10));
$this->assertEquals(NAN, $calcMock->divideBy(0));
}

There are many options that you can apply to expects. Refer to this table: http://www.phpunit.de/manual/3.0/en/mock-objects.html#mock-objects.tables.matchers Oddly I could not find the same documentation on the current version of phpunit.

Lastly, if our calculator outputted data via a function, we can still test the output by mocking the output function.

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
// Calculator.php
class Calculator {
public function getNumberFromUserInput() {
// complicated function to get number from user input
}
 
public function printToScreen($value) {
// another complicated function
}
 
public function divideBy($num2) {
if ($num2 == 0) $this->printToScreen("NaN");
$this->printToScreen($this->getNumberFromUserInput()/$num2);
}
 
// CalculatorTest.php
..
public function testDivideByPositiveNumber() {
        $calcMock=$this->getMock('\Calculator',array('getNumberFromUserInput', 'printToScreen'));
        $calcMock->expects($this->once())
            ->method('getNumberFromUserInput')
            ->will($this->returnValue(10));
        $calcMock->expects($this->once())
            ->method('printToScreen')
            ->with($this->equalTo('5')); 
        $calcMock->divideBy(2);
    }
..

->with() will test the that the method is called with parameters passed. If your original function has multiple parameters, just add them in as multiple arguments to with(). ->with($this->equalTo($param1), $this->anything(),$this->equalTo($param3)). You can use any of the constraints that phpunit supports – http://www.phpunit.de/manual/3.2/en/api.html#api.assert.tables.constraints

You can git clone this full example on my github gist – https://gist.github.com/4558701

So with that said, test your code! With mocking, it makes it dead simple to test things. There should be no excuse to having tests on all the aspects of your code.

Git New Remote Branch Cheatsheet

I seem to do this everyday on the job when I am coding and then forget on those weeks that I don’t code. Here’s the quickest way to create a remote branch that is tracked locally and remotely.

1
2
git checkout -b new_branch_name
git push -u origin new_branch_name

No fiddling around with git branch creation and checkout, then –set-upstream, All done in those 2 commands. The first command creates a new branch and sets that as your working tree. The second command pushes the current branch upstream to origin and at the same time handles –set-upstream to the given location. Neat? :)

While we’re at it, here’s how to delete it if you don’t need it anymore.

1
2
git push origin :new_branch_name
git branch -d new_branch_name

Branch all gone both locally and on the remote repository.

You can read this link if you are unfamiliar with git branching:

http://www.gitguys.com/topics/adding-and-removing-remote-branches/

Windows Master Installer

I got tired of having to have different media for installing the various versions of Windows 7 and Win 2k8 so I put together a master install disk. The procedure on how to do so has been around for a long time on the net, but I decided to automate it so I can repeat this in the future if I wanted to add other versions of Windows (say Win 8?).

Credit goes to “Explicit” for his original guide.

Without Further to do, here’s the batch script.

 

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
@echo off
 
set IMAGEXBIN="C:\Program Files\Windows AIK\Tools\amd64\imagex.exe"
set SEVENZIPBIN="C:\Program Files\7-Zip\7z.exe"
set OSCDIMGBIN="C:\Program Files\Windows AIK\Tools\amd64\oscdimg.exe"
 
set WIN7X86ISO="..\en_windows_7_ultimate_with_sp1_x86_dvd_u_677460.iso"
set WIN7X64ISO="..\en_windows_7_ultimate_with_sp1_x64_dvd_u_677332.iso"
set WIN2K8ISO="..\en_windows_server_2008_r2_with_sp1_x64_dvd_617601.iso"

rem extract everything from the ISOs
%SEVENZIPBIN% x -ox64 %WIN7X64ISO%
%SEVENZIPBIN% x -ox86 %WIN7X86ISO%
%SEVENZIPBIN% x -oServer %WIN2K8ISO%

rem let's gather the win7 64bit installers
 
%IMAGEXBIN% /export x64\sources\install.wim 2 x86\sources\install.wim "Windows 7 HOMEPREMIUM x64"
%IMAGEXBIN% /export x64\sources\install.wim 3 x86\sources\install.wim "Windows 7 PROFESSIONAL x64"
%IMAGEXBIN% /export x64\sources\install.wim 4 x86\sources\install.wim "Windows 7 ULTIMATE x64"

rem let's gather the win server 2k8 installers
 
%IMAGEXBIN% /export Server\sources\install.wim 1 x86\sources\install.wim "Windows Server 2008 R2 SERVERSTANDARD"
%IMAGEXBIN% /export Server\sources\install.wim 2 x86\sources\install.wim "Windows Server 2008 R2 SERVERSTANDARDCORE"
%IMAGEXBIN% /export Server\sources\install.wim 3 x86\sources\install.wim "Windows Server 2008 R2 SERVERENTERPRISE"
%IMAGEXBIN% /export Server\sources\install.wim 4 x86\sources\install.wim "Windows Server 2008 R2 SERVERENTERPRISECORE"
%IMAGEXBIN% /export Server\sources\install.wim 5 x86\sources\install.wim "Windows Server 2008 R2 SERVERDATACENTER"
%IMAGEXBIN% /export Server\sources\install.wim 6 x86\sources\install.wim "Windows Server 2008 R2 SERVERDATACENTERCORE"
%IMAGEXBIN% /export Server\sources\install.wim 7 x86\sources\install.wim "Windows Server 2008 R2 SERVERWEB"
%IMAGEXBIN% /export Server\sources\install.wim 8 x86\sources\install.wim "Windows Server 2008 R2 SERVERWEBCORE"

rem copy the EULA for boot.wim
 
mkdir serverMount
%IMAGEXBIN% /mountrw Server\sources\boot.wim 2 serverMount
 
mkdir win7Mount
%IMAGEXBIN% /mountrw x86\sources\boot.wim 2 win7Mount
 
xcopy /E serverMount\sources\License win7Mount\sources\License
 
%IMAGEXBIN% /unmount /commit win7Mount
 
%IMAGEXBIN% /unmount serverMount
 
rmdir serverMount
rmdir win7Mount

rem copy the EULA for installing from within windows.
 
xcopy /E Server\sources\License x86\sources\License
 
copy Server\sources\install*.clg x86\sources\
 
del x86\sources\ei.cfg

rem create bootable disk
 
%OSCDIMGBIN% -lGRMCULFRER_EN_DVD -m -u2 -o -h -bx86\boot\etfsboot.com x86 Windows7and2008R2AIO.iso

rem cleanup afterwards, uncomment to run

rem rmdir /s x86
rem rmdir /s server
rem rmdir /s x64

Recovering Data from a corrupt RapidDrive Partition

I had a Lenovo Y570 I recently had to repair. It seemed like a straightforward job to mount the HDD using my favorite LiveCD and copy the data to a secondary hard drive. I quickly found out it wasn’t that straightforward. On this model, there was a 750GB hard drive with a 64GB SSD that was hybridly merged together using something called RapidDrive. The technology dynamically copies data between the HDD and SSD so that you can get the best of both worlds in terms of performance and space. Unfortunately, recovery of such systems when the drive is unbootable is almost impossible.

I booted up to my favorite live CD to find two partitions on the SSD, 1 spanning 750 GB. cfdisk would not even run because it said that this partition ends after size of the drive. The 750GB HD had several partitions on it, the largest 700GB one with all the data on it would not mount either… (probably because half of it was on the SSD!)

I could not find any information on the internet on how to mount the hard drives or recover the data. Lenovo was unhelpful and wanted to take the laptop and probably wipe it and give it back to me. I noticed though that when you run the “OneKey Recovery System” that the virus scanner was able to read the hybrid partition of data. There was hope of recovering the data.

Unfortunately though, OneKey Recovery gives you only 2 options, scan for viruses or wipe the hard drive and restore. I wish they would give me a command prompt or something. I tried numerous things such as booting OneKey Recovery System in safe mode and other things like that. Nothing worked. I finally dived into the internals and forced a command prompt to load up.

Here’s how.

Items Needed:

  • Favorite LiveCD that can mount ntfs drives
  • External drive to backup and copy data
  • Windows AIK
  • 2nd Windows 7 Computer

Steps:

  1. Boot off your live CD. Identify the recovery partition. On my system, the SSD was /dev/sda and the HDD was /dev/sdb. The recovery system was on /dev/sdb3.
    1
    2
    
    $ mount /dev/sdb3 /mnt/local
    $ mount /dev/sdc1 /mnt/usb # storage drive


  2. Make a backup, then copy off the wim file off the recovery partition.
    1
    2
    3
    
    # the filenames may be off since I am writing this from memory
    $ cp /mnt/local/Onekey/PE/lrs.wim /mnt/local/Onekey/PE/lrs.wim.original
    $ cp /mnt/local/Onekey/PE/lrs.wim /mnt/usb/


  3. Unmount your external drive and bring it to your windows machine with AIK installed on it. Mount the wim and update the boot loader file. You must run all the following commands as administrator (right click on cmd.exe and click “run as administrator”)
    1
    2
    3
    
    mkdir lrs-mount
    "C:\Program Files\Windows AIK\Tools\x86\imagex.exe" /mountrw lrs.wim 1 lrs-mount
    notepad lrs-mount\windows\system32\winpeshl.ini

    winpeshl.ini should be changed to:

    1
    2
    
    [LaunchApps]
    %SYSTEMDRIVE%\windows\system32\cmd.exe
    1
    2
    
    "C:\Program Files\Windows AIK\Tools\x86\imagex.exe" /commit lrs-mount
    "C:\Program Files\Windows AIK\Tools\x86\imagex.exe" /unmount lrs-mount
  4. Copy the lrs.wim back to the original location and shutdown and restart using the “OneKey” button. When you startup, you should get a command prompt instead of the one click install. On my computer, e: was the hard drive. There seems to be 3-4 drives, c:, d:, e:, x:, perhaps even more. You’ll have to search.

Heap Sort Visualization #2

I enhanced the heap sort algorithm code so it may be more useful for teaching purposes. Enjoy! Feel free to use it wherever you want, and if you find it really useful, leave me a comment!




Source code: HeapSort RandomArray

Built with Processing