From 1ed17e94b1aea32a988b4ca0f9213519de557bee Mon Sep 17 00:00:00 2001 From: victor Date: Mon, 25 Feb 2019 15:57:21 +0900 Subject: [PATCH] =?UTF-8?q?=EC=A0=84=EC=A3=BC=EA=B8=B0=20=EC=8B=9C?= =?UTF-8?q?=EC=97=B0=EC=9A=A9=20=EC=9D=91=EC=9A=A9=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EB=9E=A8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go/src/fullcycle/analog-kernel/input-sample | 294 ++++++++++++ go/src/fullcycle/analog-kernel/main.go | 100 ++++ go/src/fullcycle/analog-kernel/parser/device.go | 64 +++ go/src/fullcycle/analog-kernel/parser/parse.go | 586 +++++++++++++++++++++++ go/src/fullcycle/analog-kernel/parser/parser.go | 250 ++++++++++ go/src/fullcycle/analog-kernel/sheet-sample.json | 203 ++++++++ go/src/fullcycle/analog-kernel/test.sh | 3 + go/src/fullcycle/do-iperf/main.go | 56 +++ 8 files changed, 1556 insertions(+) create mode 100644 go/src/fullcycle/analog-kernel/input-sample create mode 100644 go/src/fullcycle/analog-kernel/main.go create mode 100644 go/src/fullcycle/analog-kernel/parser/device.go create mode 100644 go/src/fullcycle/analog-kernel/parser/parse.go create mode 100644 go/src/fullcycle/analog-kernel/parser/parser.go create mode 100644 go/src/fullcycle/analog-kernel/sheet-sample.json create mode 100755 go/src/fullcycle/analog-kernel/test.sh create mode 100644 go/src/fullcycle/do-iperf/main.go diff --git a/go/src/fullcycle/analog-kernel/input-sample b/go/src/fullcycle/analog-kernel/input-sample new file mode 100644 index 0000000..f4afbbc --- /dev/null +++ b/go/src/fullcycle/analog-kernel/input-sample @@ -0,0 +1,294 @@ +[ 0.000000] Booting Linux on physical CPU 0x0 +[ 0.000000] Linux version 4.9.80-v7+ (dc4@dc4-XPS13-9333) (gcc version 4.9.3 (crosstool-NG crosstool-ng-1.22.0-88-g8460611) ) #1098 SMP Fri Mar 9 19:11:42 GMT 2018 +[ 0.000000] CPU: ARMv7 Processor [410fd034] revision 4 (ARMv7), cr=10c5383d +[ 0.000000] CPU: div instructions available: patching division code +[ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache +[ 0.000000] OF: fdt:Machine model: Raspberry Pi 3 Model B Rev 1.2 +[ 0.000000] cma: Reserved 8 MiB at 0x3ac00000 +[ 0.000000] Memory policy: Data cache writealloc +[ 0.000000] percpu: Embedded 14 pages/cpu @ba35b000 s25600 r8192 d23552 u57344 +[ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pages: 240555 +[ 0.000000] Kernel command line: 8250.nr_uarts=1 bcm2708_fb.fbwidth=656 bcm2708_fb.fbheight=416 bcm2708_fb.fbswap=1 vc_mem.mem_base=0x3ec00000 vc_mem.mem_size=0x40000000 dwc_otg.lpm_enable=0 console=ttyS0,115200 console=tty1 root=PARTUUID=c80dc558-02 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait +[ 0.000000] PID hash table entries: 4096 (order: 2, 16384 bytes) +[ 0.000000] Dentry cache hash table entries: 131072 (order: 7, 524288 bytes) +[ 0.000000] Inode-cache hash table entries: 65536 (order: 6, 262144 bytes) +[ 0.000000] Memory: 940364K/970752K available (7168K kernel code, 487K rwdata, 2032K rodata, 1024K init, 770K bss, 22196K reserved, 8192K cma-reserved) +[ 0.000000] Virtual kernel memory layout: +[ 0.000000] vector : 0xffff0000 - 0xffff1000 ( 4 kB) +[ 0.000000] fixmap : 0xffc00000 - 0xfff00000 (3072 kB) +[ 0.000000] vmalloc : 0xbb800000 - 0xff800000 (1088 MB) +[ 0.000000] lowmem : 0x80000000 - 0xbb400000 ( 948 MB) +[ 0.000000] modules : 0x7f000000 - 0x80000000 ( 16 MB) +[ 0.000000] .text : 0x80008000 - 0x80800000 (8160 kB) +[ 0.000000] .init : 0x80b00000 - 0x80c00000 (1024 kB) +[ 0.000000] .data : 0x80c00000 - 0x80c79cbc ( 488 kB) +[ 0.000000] .bss : 0x80c7b000 - 0x80d3b9e4 ( 771 kB) +[ 0.000000] SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1 +[ 0.000000] Hierarchical RCU implementation. +[ 0.000000] Build-time adjustment of leaf fanout to 32. +[ 0.000000] NR_IRQS:16 nr_irqs:16 16 +[ 0.000000] arm_arch_timer: Architected cp15 timer(s) running at 19.20MHz (phys). +[ 0.000000] clocksource: arch_sys_counter: mask: 0xffffffffffffff max_cycles: 0x46d987e47, max_idle_ns: 440795202767 ns +[ 0.000007] sched_clock: 56 bits at 19MHz, resolution 52ns, wraps every 4398046511078ns +[ 0.000022] Switching to timer-based delay loop, resolution 52ns +[ 0.000301] Console: colour dummy device 80x30 +[ 0.001189] console [tty1] enabled +[ 0.001237] Calibrating delay loop (skipped), value calculated using timer frequency.. 38.40 BogoMIPS (lpj=192000) +[ 0.001304] pid_max: default: 32768 minimum: 301 +[ 0.001640] Mount-cache hash table entries: 2048 (order: 1, 8192 bytes) +[ 0.001682] Mountpoint-cache hash table entries: 2048 (order: 1, 8192 bytes) +[ 0.002721] Disabling memory control group subsystem +[ 0.002825] CPU: Testing write buffer coherency: ok +[ 0.002889] ftrace: allocating 22627 entries in 67 pages +[ 0.050538] CPU0: update cpu_capacity 1024 +[ 0.050590] CPU0: thread -1, cpu 0, socket 0, mpidr 80000000 +[ 0.050651] Setting up static identity map for 0x100000 - 0x100034 +[ 0.052502] CPU1: update cpu_capacity 1024 +[ 0.052509] CPU1: thread -1, cpu 1, socket 0, mpidr 80000001 +[ 0.053151] CPU2: update cpu_capacity 1024 +[ 0.053158] CPU2: thread -1, cpu 2, socket 0, mpidr 80000002 +[ 0.053782] CPU3: update cpu_capacity 1024 +[ 0.053788] CPU3: thread -1, cpu 3, socket 0, mpidr 80000003 +[ 0.053876] Brought up 4 CPUs +[ 0.054049] SMP: Total of 4 processors activated (153.60 BogoMIPS). +[ 0.054078] CPU: All CPU(s) started in HYP mode. +[ 0.054105] CPU: Virtualization extensions available. +[ 0.054925] devtmpfs: initialized +[ 0.066064] VFP support v0.3: implementor 41 architecture 3 part 40 variant 3 rev 4 +[ 0.066387] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns +[ 0.066447] futex hash table entries: 1024 (order: 4, 65536 bytes) +[ 0.067005] pinctrl core: initialized pinctrl subsystem +[ 0.067938] NET: Registered protocol family 16 +[ 0.070178] DMA: preallocated 1024 KiB pool for atomic coherent allocations +[ 0.078975] hw-breakpoint: found 5 (+1 reserved) breakpoint and 4 watchpoint registers. +[ 0.079024] hw-breakpoint: maximum watchpoint size is 8 bytes. +[ 0.079206] Serial: AMBA PL011 UART driver +[ 0.081108] bcm2835-mbox 3f00b880.mailbox: mailbox enabled +[ 0.081656] uart-pl011 3f201000.serial: could not find pctldev for node /soc/gpio@7e200000/uart0_pins, deferring probe +[ 0.082020] irq: no irq domain found for /soc/aux@0x7e215000 ! +[ 0.151380] bcm2835-dma 3f007000.dma: DMA legacy API manager at bb80d000, dmachans=0x1 +[ 0.153246] SCSI subsystem initialized +[ 0.153569] usbcore: registered new interface driver usbfs +[ 0.153679] usbcore: registered new interface driver hub +[ 0.153796] usbcore: registered new device driver usb +[ 0.160347] raspberrypi-firmware soc:firmware: Attached to firmware from 2018-03-13 18:45 +[ 0.161752] clocksource: Switched to clocksource arch_sys_counter +[ 0.209297] VFS: Disk quotas dquot_6.6.0 +[ 0.209409] VFS: Dquot-cache hash table entries: 1024 (order 0, 4096 bytes) +[ 0.209638] FS-Cache: Loaded +[ 0.209906] CacheFiles: Loaded +[ 0.222053] NET: Registered protocol family 2 +[ 0.222946] TCP established hash table entries: 8192 (order: 3, 32768 bytes) +[ 0.223084] TCP bind hash table entries: 8192 (order: 4, 65536 bytes) +[ 0.223295] TCP: Hash tables configured (established 8192 bind 8192) +[ 0.223407] UDP hash table entries: 512 (order: 2, 16384 bytes) +[ 0.223474] UDP-Lite hash table entries: 512 (order: 2, 16384 bytes) +[ 0.223706] NET: Registered protocol family 1 +[ 0.224139] RPC: Registered named UNIX socket transport module. +[ 0.224171] RPC: Registered udp transport module. +[ 0.224199] RPC: Registered tcp transport module. +[ 0.224226] RPC: Registered tcp NFSv4.1 backchannel transport module. +[ 0.225201] hw perfevents: enabled with armv7_cortex_a7 PMU driver, 7 counters available +[ 0.227516] workingset: timestamp_bits=14 max_order=18 bucket_order=4 +[ 0.243575] FS-Cache: Netfs 'nfs' registered for caching +[ 0.244570] NFS: Registering the id_resolver key type +[ 0.244620] Key type id_resolver registered +[ 0.244648] Key type id_legacy registered +[ 0.247075] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 251) +[ 0.247226] io scheduler noop registered +[ 0.247256] io scheduler deadline registered (default) +[ 0.247542] io scheduler cfq registered +[ 0.253205] BCM2708FB: allocated DMA memory fad10000 +[ 0.253258] BCM2708FB: allocated DMA channel 0 @ bb80d000 +[ 0.261949] Console: switching to colour frame buffer device 82x26 +[ 0.269369] Serial: 8250/16550 driver, 1 ports, IRQ sharing enabled +[ 0.273301] bcm2835-rng 3f104000.rng: hwrng registered +[ 0.275682] vc-mem: phys_addr:0x00000000 mem_base=0x3ec00000 mem_size:0x40000000(1024 MiB) +[ 0.280940] vc-sm: Videocore shared memory driver +[ 0.298295] brd: module loaded +[ 0.309480] loop: module loaded +[ 0.311864] Loading iSCSI transport class v2.0-870. +[ 0.314857] libphy: Fixed MDIO Bus: probed +[ 0.317213] usbcore: registered new interface driver lan78xx +[ 0.319579] usbcore: registered new interface driver smsc95xx +[ 0.321831] dwc_otg: version 3.00a 10-AUG-2012 (platform bus) +[ 0.552154] Core Release: 2.80a +[ 0.554363] Setting default values for core params +[ 0.556552] Finished setting default values for core params +[ 0.759140] Using Buffer DMA mode +[ 0.761337] Periodic Transfer Interrupt Enhancement - disabled +[ 0.763656] Multiprocessor Interrupt Enhancement - disabled +[ 0.765971] OTG VER PARAM: 0, OTG VER FLAG: 0 +[ 0.768319] Dedicated Tx FIFOs mode +[ 0.770929] WARN::dwc_otg_hcd_init:1032: FIQ DMA bounce buffers: virt = 0xbad04000 dma = 0xfad04000 len=9024 +[ 0.775666] FIQ FSM acceleration enabled for : +[ 0.775666] Non-periodic Split Transactions +[ 0.775666] Periodic Split Transactions +[ 0.775666] High-Speed Isochronous Endpoints +[ 0.775666] Interrupt/Control Split Transaction hack enabled +[ 0.786746] WARN::hcd_init_fiq:459: FIQ on core 1 at 0x8059b380 +[ 0.789026] WARN::hcd_init_fiq:460: FIQ ASM at 0x8059b6f0 length 36 +[ 0.791285] WARN::hcd_init_fiq:486: MPHI regs_base at 0xbb878000 +[ 0.793550] dwc_otg 3f980000.usb: DWC OTG Controller +[ 0.795866] dwc_otg 3f980000.usb: new USB bus registered, assigned bus number 1 +[ 0.798224] dwc_otg 3f980000.usb: irq 62, io mem 0x00000000 +[ 0.800538] Init: Port Power? op_state=1 +[ 0.802811] Init: Power Port (0) +[ 0.805198] usb usb1: New USB device found, idVendor=1d6b, idProduct=0002 +[ 0.807508] usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1 +[ 0.809802] usb usb1: Product: DWC OTG Controller +[ 0.812061] usb usb1: Manufacturer: Linux 4.9.80-v7+ dwc_otg_hcd +[ 0.814327] usb usb1: SerialNumber: 3f980000.usb +[ 0.817410] hub 1-0:1.0: USB hub found +[ 0.819607] hub 1-0:1.0: 1 port detected +[ 0.822544] usbcore: registered new interface driver usb-storage +[ 0.824871] mousedev: PS/2 mouse device common for all mice +[ 0.827965] bcm2835-wdt 3f100000.watchdog: Broadcom BCM2835 watchdog timer +[ 0.830488] bcm2835-cpufreq: min=600000 max=1200000 +[ 0.833165] sdhci: Secure Digital Host Controller Interface driver +[ 0.835478] sdhci: Copyright(c) Pierre Ossman +[ 0.838000] sdhost-bcm2835 3f202000.sdhost: could not get clk, deferring probe +[ 0.842594] mmc-bcm2835 3f300000.mmc: could not get clk, deferring probe +[ 0.845137] sdhci-pltfm: SDHCI platform and OF driver helper +[ 0.849016] ledtrig-cpu: registered to indicate activity on CPUs +[ 0.851668] hidraw: raw HID events driver (C) Jiri Kosina +[ 0.854366] usbcore: registered new interface driver usbhid +[ 0.856826] usbhid: USB HID core driver +[ 0.860069] vchiq: vchiq_init_state: slot_zero = 0xbad80000, is_master = 0 +[ 0.863954] [vc_sm_connected_init]: start +[ 0.872620] [vc_sm_connected_init]: end - returning 0 +[ 0.875442] Initializing XFRM netlink socket +[ 0.877894] NET: Registered protocol family 17 +[ 0.880431] Key type dns_resolver registered +[ 0.883248] Registering SWP/SWPB emulation handler +[ 0.886437] registered taskstats version 1 +[ 0.895220] uart-pl011 3f201000.serial: cts_event_workaround enabled +[ 0.897794] 3f201000.serial: ttyAMA0 at MMIO 0x3f201000 (irq = 87, base_baud = 0) is a PL011 rev2 +[ 0.904299] console [ttyS0] disabled +[ 0.906753] 3f215040.serial: ttyS0 at MMIO 0x0 (irq = 220, base_baud = 31250000) is a 16550 +[ 1.899569] console [ttyS0] enabled +[ 1.906298] sdhost: log_buf @ bad07000 (fad07000) +[ 1.991780] mmc0: sdhost-bcm2835 loaded - DMA enabled (>1) +[ 2.001958] mmc-bcm2835 3f300000.mmc: mmc_debug:0 mmc_debug2:0 +[ 2.010292] mmc-bcm2835 3f300000.mmc: DMA channel allocated +[ 2.039017] Indeed it is in host mode hprt0 = 00021501 +[ 2.131876] of_cfs_init +[ 2.133893] random: fast init done +[ 2.142450] of_cfs_init: OK +[ 2.147979] Waiting for root device PARTUUID=c80dc558-02... +[ 2.151869] mmc1: queuing unknown CIS tuple 0x80 (2 bytes) +[ 2.153435] mmc1: queuing unknown CIS tuple 0x80 (3 bytes) +[ 2.155002] mmc1: queuing unknown CIS tuple 0x80 (3 bytes) +[ 2.157820] mmc1: queuing unknown CIS tuple 0x80 (7 bytes) +[ 2.213728] mmc0: host does not support reading read-only switch, assuming write-enable +[ 2.232871] mmc0: new high speed SDHC card at address aaaa +[ 2.241224] mmcblk0: mmc0:aaaa SC16G 14.8 GiB +[ 2.247801] usb 1-1: new high-speed USB device number 2 using dwc_otg +[ 2.256822] Indeed it is in host mode hprt0 = 00001101 +[ 2.329935] mmcblk0: p1 p2 +[ 2.357583] mmc1: new high speed SDIO card at address 0001 +[ 2.427039] EXT4-fs (mmcblk0p2): INFO: recovery required on readonly filesystem +[ 2.436690] EXT4-fs (mmcblk0p2): write access will be enabled during recovery +[ 2.458484] EXT4-fs (mmcblk0p2): recovery complete +[ 2.467210] EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. Opts: (null) +[ 2.479804] VFS: Mounted root (ext4 filesystem) readonly on device 179:2. +[ 2.492049] usb 1-1: New USB device found, idVendor=0424, idProduct=9514 +[ 2.500151] devtmpfs: mounted +[ 2.506664] usb 1-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0 +[ 2.518166] Freeing unused kernel memory: 1024K +[ 2.526223] hub 1-1:1.0: USB hub found +[ 2.532766] hub 1-1:1.0: 5 ports detected +[ 2.851799] usb 1-1.1: new high-speed USB device number 3 using dwc_otg +[ 2.960961] systemd[1]: System time before build time, advancing clock. +[ 2.982100] usb 1-1.1: New USB device found, idVendor=0424, idProduct=ec00 +[ 2.991832] usb 1-1.1: New USB device strings: Mfr=0, Product=0, SerialNumber=0 +[ 3.004854] smsc95xx v1.0.5 +[ 3.081379] NET: Registered protocol family 10 +[ 3.102250] ip_tables: (C) 2000-2006 Netfilter Core Team +[ 3.105781] smsc95xx 1-1.1:1.0 eth0: register 'smsc95xx' at usb-3f980000.usb-1.1, smsc95xx USB 2.0 Ethernet, b8:27:eb:d1:b3:bf +[ 3.152858] systemd[1]: systemd 232 running in system mode. (+PAM +AUDIT +SELINUX +IMA +APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +SECCOMP +BLKID +ELFUTILS +KMOD +IDN) +[ 3.180405] systemd[1]: Detected architecture arm. +[ 3.204807] systemd[1]: Set hostname to . +[ 3.655243] systemd[1]: Listening on udev Kernel Socket. +[ 3.666913] systemd[1]: Started Forward Password Requests to Wall Directory Watch. +[ 3.683625] systemd[1]: Listening on Journal Socket. +[ 3.694815] systemd[1]: Listening on Syslog Socket. +[ 3.706356] systemd[1]: Created slice System Slice. +[ 3.719823] systemd[1]: Mounting RPC Pipe File System... +[ 3.735831] systemd[1]: Starting Restore / save the current clock... +[ OK ] Started Show Plymouth Boot Screen. +[ OK ] Reached target Encrypted Volumes. +[ OK ] Reached target Paths. +[ OK ] Started Forward Password Requests to Plymouth Directory Watch. +[ OK ] Started File System Check on /dev/disk/by-partuuid/c80dc558-01. + Mounting /boot... +[ OK ] Mounted /boot. +[ OK ] Reached target Local File Systems. + Starting Set console font and keymap... + Starting Tell Plymouth To Write Out Runtime Data... + Starting Raise network interfaces... + Starting Preprocess NFS configuration... + Starting Create Volatile Files and Directories... +[ OK ] Started Tell Plymouth To Write Out Runtime Data. +[ OK ] Started Preprocess NFS configuration. +[ OK ] Reached target NFS client services. +[ OK ] Reached target Remote File Systems (Pre). +[ OK ] Reached target Remote File Systems. +[ OK ] Started Create Volatile Files and Directories. + Starting Network Time Synchronization... + Starting Update UTMP about System Boot/Shutdown... +[ OK ] Started Update UTMP about System Boot/Shutdown. +[ OK ] Started Network Time Synchronization. +[ OK ] Reached target System Initialization. +[ OK ] Listening on triggerhappy.socket. +[ OK ] Listening on Avahi mDNS/DNS-SD Stack Activation Socket. +[ OK ] Listening on D-Bus System Message Bus Socket. +[ OK ] Reached target Sockets. +[ OK ] Reached target Basic System. + Starting LSB: Switch to ondemand cpu…or (unless shift key is pressed)... + Starting System Logging Service... + Starting LSB: Autogenerate and use a swap file... +[ OK ] Started Regular background program processing daemon. + Starting dhcpcd on all interfaces... + Starting triggerhappy global hotkey daemon... + Starting Save/Restore Sound Card State... + Starting Configure Bluetooth Modems connected by UART... + Starting Avahi mDNS/DNS-SD Stack... +[ OK ] Started D-Bus System Message Bus. +[ OK ] Started Avahi mDNS/DNS-SD Stack. + Starting Disable WiFi if country not set... +[ OK ] Started Daily Cleanup of Temporary Directories. + Starting Login Service... +[ OK ] Reached target System Time Synchronized. +[ OK ] Started Daily apt download activities. +[ OK ] Started Daily apt upgrade and clean activities. +[ OK ] Reached target Timers. +[ OK ] Started triggerhappy global hotkey daemon. +[ OK ] Started System Logging Service. +[ OK ] Started Save/Restore Sound Card State. +[ OK ] Started Disable WiFi if country not set. + Starting Load/Save RF Kill Switch Status... +[ OK ] Started Login Service. +[ OK ] Started Raise network interfaces. +[ OK ] Started LSB: Switch to ondemand cpu …rnor (unless shift key is pressed). +[ OK ] Started Load/Save RF Kill Switch Status. +[ OK ] Started LSB: Autogenerate and use a swap file. +[ OK ] Started Configure Bluetooth Modems connected by UART. + Starting Bluetooth service... +[ OK ] Started Bluetooth service. +[ OK ] Reached target Bluetooth. + Starting Hostname Service... +[ OK ] Started Hostname Service. +[ OK ] Started Set console font and keymap. +[ OK ] Started dhcpcd on all interfaces. +[ OK ] Reached target Network. + Starting /etc/rc.local Compatibility... + Starting Permit User Sessions... +[ OK ] Started /etc/rc.local Compatibility. +[ OK ] Started Permit User Sessions. + Starting Terminate Plymouth Boot Screen... + Starting Hold until boot process finishes up... + +Raspbian GNU/Linux 9 raspberrypi ttyS0 +raspberrypi login: +end of kernel diff --git a/go/src/fullcycle/analog-kernel/main.go b/go/src/fullcycle/analog-kernel/main.go new file mode 100644 index 0000000..c7400c5 --- /dev/null +++ b/go/src/fullcycle/analog-kernel/main.go @@ -0,0 +1,100 @@ +package main + +import ( + "bufio" + "encoding/json" + "fmt" + "io/ioutil" + "log" + "os" + + "fullcycle/analog-kernel/parser" +) + +const defaultResult = ` +{ + "result": { + "cpu" : { + "name": "ARMv7 Processor", + "id": "410fd034", + "revision": "4", + "arch": "ARMv7", + "cr": "10c5383d" + }, + + "model" : { + "model": "Raspberry Pi 3 Model B Rev 1.2" + } + }, + + "report": { + "log_id": "012-3233-4423", + "date": "2018/04/18", + + "target": "raspberry pi3", + "hardware": [ + { + "title": "CPU", + "result": "PASS" + }, + { + "title": "Memory", + "result": "FAIL", + "message": "Not found in booting log messages" + } + ], + + "os": [ + ], + + "device": [ + ] + } +} +` + +func check(err error) { + if err != nil { + log.Fatal(err) + } +} + +var uuid string + +func init() { + if len(os.Args) == 1 { + fmt.Fprintf(os.Stderr, "Usage: %v \n", os.Args[0]) + os.Exit(1) + } + + uuid = os.Args[1] +} + +func main() { + var r parser.Request + + // Read the sheet. + fname := fmt.Sprintf("sheet-%v.json", uuid) + b, err := ioutil.ReadFile(fname) + check(err) + + err = json.Unmarshal(b, &r.Sheet) + check(err) + + // Read stdin. + s := bufio.NewScanner(os.Stdin) + for s.Scan() { + if l := s.Text(); l == "end of kernel" { + break + } else { + r.Log = append(r.Log, l) + } + } + + // Parse. + p := parser.New() + result := p.Parse(&r) + + // Print. + fmt.Print(result) +} diff --git a/go/src/fullcycle/analog-kernel/parser/device.go b/go/src/fullcycle/analog-kernel/parser/device.go new file mode 100644 index 0000000..1de38cc --- /dev/null +++ b/go/src/fullcycle/analog-kernel/parser/device.go @@ -0,0 +1,64 @@ +package parser + +import "regexp" + +type deviceTableElement struct { + name string + reString string + re *regexp.Regexp +} + +var deviceTable = []deviceTableElement{ + {"AMBA PL011 UART Device", "Serial: AMBA PL011 UART driver", nil}, + {"BCM2835 Mailbox", "bcm2835-mbox[[:print:]]+mailbox enabled", nil}, + {"BCM2835 DMA", "bcm2835-dma[[:print:]]+DMA legacy API manager", nil}, + {"RaspberryPi Firmware", "raspberrypi-firmware soc:firmware: Attached to firmware", nil}, + {"BCM2708FB", "BCM2708FB: allocated DMA memory", nil}, + {"BCM2835 RNG", "bcm2835-rng[[:print:]]+hwrng registered", nil}, + {"Videocore Memory", "vc-mem: phys_addr:", nil}, + {"Videocore Shared Memory", "vc-sm: Videocore shared memory driver", nil}, + {"Microchip LAN78XX Based USB Ethernet Adapter", "new interface driver lan78xx", nil}, + {"SMSC LAN95XX Based USB 2.0 10/100 Ethernet Device", "new interface driver smsc95xx", nil}, + {"DesignWare OTG", "dwc_otg: version ", nil}, + {"USB Mass Storage", "new interface driver usb-storage", nil}, + {"BCM2835 Watchdog Timer", "bcm2835-wdt[[:print:]]+Broadcom BCM2835 watchdog timer", nil}, + {"BCM2835 CPU Frequency Scaler", "bcm2835-cpufreq: min=", nil}, + {"Secure Digital Host Controller Interface", "sdhci: Secure Digital Host Controller Interface driver", nil}, + {"8250/16550 Serial Device", "Serial: 8250/16550 driver", nil}, + {"SDHC Card", "new high speed SDHC card", nil}, + {"SDIO Card", "new high speed SDIO card", nil}, + {"S3C Power Management", "S3C Power Management, Copyright 2004 Simtec Electronics", nil}, + {"SCSI subsystem", "SCSI subsystem initialized", nil}, + {"ARM Mali", "Mali: Mali device driver loaded", nil}, + {"Generic vibrator", "vibrator_init: vibrator", nil}, + {"Broadcom Dongle Host Driver", "dhd_module_init in", nil}, + {"Intel® Performance Counter Monitor", "intel_pmu_driver [[:print:]]+: after pmu initialization", nil}, + {"Generic Wi-Fi", "found wifi platform device wlan", nil}, + {"Broadcom SDIO", "bcmsdh_sdmmc: bcmsdh_sdmmc_probe Enter", nil}, + {"s3c64xx SPI", "s3c64xx-spi 13920000.spi: spi bus clock parent not specified, using clock at index 0 as parent", nil}, + {"NLS-HR22", "hid-generic [0-9]+:1EAB:1A03.[0-9]+: input,hidraw[0-9]+: USB HID v1.00 Keyboard", nil}, + {"CP210X", "cp210x [0-9]+-[0-9]+.[0-9]+:[0-9]+.[0-9]+: cp210x converter detected", nil}, + {"NetWinder Floating Point Emulator", "NetWinder Floating Point Emulator", nil}, + {"Block layer SCSI generic", "Block layer SCSI generic \\(bsg\\) driver", nil}, + {"SCSI Media Changer", "SCSI Media Changer driver", nil}, + {"Nuvoton NUC970 EHCI Host Controller", "Nuvoton NUC970 EHCI Host Controller", nil}, + {"Nuvoton NUC970 OHCI Host Controller", "Nuvoton NUC970 OHCI Host Controller", nil}, + {"Wireless RNDIS USB", "new interface driver rndis_wlan", nil}, + {"ASIX AX88xxx Based USB 2.0 Ethernet Adapters", "new interface driver asix", nil}, + {"ASIX AX88179/178A USB 3.0/2.0 to Gigabit Ethernet", "new interface driver ax88179_178a", nil}, + {"CDC Ethernet", "new interface driver cdc_ether", nil}, + {"CDC EEM", "new interface driver cdc_eem", nil}, + {"NetChip 1080 based cables (Laplink, ...)", "new interface driver net1080", nil}, + {"Host for RNDIS and ActiveSync devices", "new interface driver rndis_host", nil}, + {"Simple USB Network Links (CDC Ethernet subset)", "new interface driver cdc_subset", nil}, + {"Sharp Zaurus (stock ROMs) and compatible", "new interface driver zaurus", nil}, + {"CDC NCM", "new interface driver cdc_ncm", nil}, + {"CDC MBIM", "new interface driver cdc_mbim", nil}, + {"I2C EEPROM", "at24 .* EEPROM", nil}, +} + +func init() { + for i, e := range deviceTable { + deviceTable[i].re = regexp.MustCompile(e.reString) + } +} diff --git a/go/src/fullcycle/analog-kernel/parser/parse.go b/go/src/fullcycle/analog-kernel/parser/parse.go new file mode 100644 index 0000000..d3b780a --- /dev/null +++ b/go/src/fullcycle/analog-kernel/parser/parse.go @@ -0,0 +1,586 @@ +package parser + +import ( + "regexp" + "strconv" + "strings" +) + +var parseFuncList = []func(chan string, chan jsonObject){ + parseMemory, + parseMemoryLayout, + parseTimestamps, + parseStatus, + parseHashTables, + parseLinux, + parseCpu, + parseModel, + parseDeviceFound, + parseKernelCommandLine, + parseCma, + parseSlub, + parsePidMax, + parseWorkingset, +} + +var reTimestamp = regexp.MustCompile(`^\[[[:blank:]]*[[:digit:]]+\.[[:digit:]]+[[:blank:]]*\]`) +var reAddress = regexp.MustCompile(`0x[[:xdigit:]]+`) + +func parseMemory(lines chan string, chanOutput chan jsonObject) { + m := make(jsonObject) + m["type"] = "memory" + + rLine := regexp.MustCompile("Memory: [[:ascii:]]+ available") + rBytes := regexp.MustCompile("[[:digit:]]+[Kk]") + for line := range lines { + if found := rLine.FindString(line); found != "" { + r := rBytes.FindAllString(line, 2) + m["available"] = r[0] + m["total"] = r[1] + chanOutput <- m + return + } + } + + m["available"] = "" + m["total"] = "" + + chanOutput <- m +} + +func parseMemoryLayout(lines chan string, chanOutput chan jsonObject) { + rHeaderArm := regexp.MustCompile("Virtual kernel memory layout:") + rHeaderX86 := regexp.MustCompile("Zone ranges:") + for line := range lines { + if rHeaderArm.MatchString(line) { + parseMemoryLayoutArm(lines, chanOutput) + return + } + + if rHeaderX86.MatchString(line) { + parseMemoryLayoutX86(lines, chanOutput) + return + } + } + + m := make(jsonObject) + m["type"] = "memory_layout" + m["layout"] = make([]jsonObject, 0) + + chanOutput <- m +} + +func parseMemoryLayoutArm(lines chan string, chanOutput chan jsonObject) { + m := make(jsonObject) + m["type"] = "memory_layout" + m["layout"] = make([]jsonObject, 0) + + rLine := regexp.MustCompile(`[[:print:]]+:[[:blank:]]*0x[[:xdigit:]]+[[:blank:]]*-[[:blank:]]*0x[[:xdigit:]]+`) + rLabel := regexp.MustCompile(`[[:graph:]]+`) + + for line := range lines { + line = removeTimestamp(line) + if rLine.MatchString(line) { + item := make(jsonObject) + item["label"] = rLabel.FindString(line) + + r := reAddress.FindAllString(line, 2) + item["from"] = r[0] + item["to"] = r[1] + + m["layout"] = append(m["layout"].([]jsonObject), item) + } else { + break + } + } + + chanOutput <- m +} + +func parseMemoryLayoutX86(lines chan string, chanOutput chan jsonObject) { + m := make(jsonObject) + m["type"] = "memory_layout" + m["layout"] = make([]jsonObject, 0) + + rLine := regexp.MustCompile(`[[:print:]]+\[mem[[:blank:]]+0x[[:xdigit:]]+-0x[[:xdigit:]]+\]`) + rLabel := regexp.MustCompile(`[[:graph:]]+`) + + for line := range lines { + line = removeTimestamp(line) + if rLine.MatchString(line) { + item := make(jsonObject) + item["label"] = rLabel.FindString(line) + + r := reAddress.FindAllString(line, 2) + item["from"] = r[0] + item["to"] = r[1] + + m["layout"] = append(m["layout"].([]jsonObject), item) + } else { + break + } + } + + chanOutput <- m +} + +func parseTimestamps(lines chan string, chanOutput chan jsonObject) { + rVal := regexp.MustCompile(`[[:digit:]]+\.[[:digit:]]+`) + + list := make(jsonArray, 0) + for line := range lines { + if reTimestamp.MatchString(line) { + t := reTimestamp.FindString(line) + v := rVal.FindString(t) + f, _ := strconv.ParseFloat(v, 64) + list = append(list, f) + } + } + + m := make(jsonObject) + m["type"] = "timestamps" + m["timestamps"] = list + + chanOutput <- m +} + +func parseStatus(lines chan string, chanOutput chan jsonObject) { + rLine := regexp.MustCompile(`^\[[[:blank:]]*(OK|FAIL)[[:blank:]]*\][[:blank:]]+`) + rOk := regexp.MustCompile(`^\[[[:blank:]]*OK[[:blank:]]*\]`) + + list := make([]jsonObject, 0) + for line := range lines { + if rLine.MatchString(line) { + item := make(jsonObject) + if rOk.MatchString(line) { + item["status"] = "ok" + } else { + item["status"] = "fail" + } + + prefix := rLine.FindString(line) + label := strings.TrimPrefix(line, prefix) + item["label"] = label + + list = append(list, item) + } + } + + m := make(jsonObject) + m["type"] = "status" + m["list"] = list + + chanOutput <- m +} + +func parseHashTables(lines chan string, chanOutput chan jsonObject) { + rLine := regexp.MustCompile(`[[:graph:]]+ hash table entries:`) + + list := make([]jsonObject, 0) + for line := range lines { + if rLine.MatchString(line) { + line = removeTimestamp(line) + + item := make(jsonObject) + + label := regexp.MustCompile(`[[:print:]]+ hash table entries:`).FindString(line) + + item["label"] = strings.TrimSuffix(label, " hash table entries:") + + entries := regexp.MustCompile(`hash table entries: [[:digit:]]+`).FindString(line) + entries = strings.TrimPrefix(entries, "hash table entries: ") + + item["entries"], _ = strconv.ParseInt(entries, 10, 64) + + order := regexp.MustCompile(`order:? [[:digit:]-]+`).FindString(line) + orderPrefix := regexp.MustCompile(`order:? `).FindString(order) + order = strings.TrimPrefix(order, orderPrefix) + + item["order"], _ = strconv.ParseInt(order, 10, 64) + + size := regexp.MustCompile(`[[:digit:]]+ bytes`).FindString(line) + size = strings.TrimSuffix(size, " bytes") + + item["size"], _ = strconv.ParseInt(size, 10, 64) + + list = append(list, item) + } + } + + m := make(jsonObject) + m["type"] = "hash_tables" + m["list"] = list + + chanOutput <- m +} + +func parseLinux(lines chan string, chanOutput chan jsonObject) { + m := make(jsonObject) + m["type"] = "linux" + m["version"] = "" + m["builder"] = "" + m["toolchain"] = "" + m["label"] = "" + + rLine := regexp.MustCompile(`Linux version[[:blank:]]+[[:graph:]]+[[:blank:]]+([[:print:]]+)[[:blank:]]+([[:print:]]+)[[:blank:]]+#[[:print:]]+`) + for line := range lines { + if rLine.MatchString(line) { + line = rLine.FindString(line) + line = strings.TrimPrefix(line, "Linux version ") + + m["version"] = regexp.MustCompile(`[[:graph:]]+`).FindString(line) + m["os"] = "linux" + + bracketed := regexp.MustCompile(`\([[:print:]]+?\)`).FindAllString(line, 2) + for i, s := range bracketed { + switch i { + case 0: + m["builder"] = removeBrackets(s) + case 1: + m["toolchain"] = removeBrackets(s) + } + } + + m["label"] = regexp.MustCompile(`#[[:print:]]+`).FindString(line) + + break + } + } + + chanOutput <- m +} + +func parseCpu(lines chan string, chanOutput chan jsonObject) { + m := make(jsonObject) + m["type"] = "cpu" + m["name"] = "" + m["id"] = "" + m["revision"] = "" + m["arch"] = "" + m["cr"] = "" + m["data_cache"] = "" + m["instruction_cache"] = "" + + rLine1 := regexp.MustCompile(`CPU:[[:blank:]]+[[:print:]]+[[:blank:]]+\[[[:xdigit:]]+\][[:blank:]]+revision[[:blank:]]+[[:digit:]][[:blank:]]+\([[:print:]]+\), cr=[[:xdigit:]]+`) + rLine2 := regexp.MustCompile(`CPU:[[:blank:]]+[[:print:]]+[[:blank:]]+data cache,[[:blank:]]+[[:print:]]+[[:blank:]]+instruction cache`) + for line := range lines { + if rLine1.MatchString(line) { + line = rLine1.FindString(line) + line = strings.TrimPrefix(line, "CPU: ") + + name := regexp.MustCompile(`[[:print:]]+\[`).FindString(line) + name = strings.TrimSuffix(name, "[") + name = strings.TrimSpace(name) + + m["name"] = name + + id := regexp.MustCompile(`\[[[:xdigit:]]+\]`).FindString(line) + id = strings.TrimPrefix(id, "[") + id = strings.TrimSuffix(id, "]") + + m["id"] = id + + revision := regexp.MustCompile(`revision[[:blank:]]+[[:digit:]]+`).FindString(line) + revision = strings.TrimPrefix(revision, "revision") + revision = strings.TrimSpace(revision) + + m["revision"] = revision + + arch := regexp.MustCompile(`\([[:print:]]+\)`).FindString(line) + arch = strings.TrimPrefix(arch, "(") + arch = strings.TrimSuffix(arch, ")") + arch = strings.TrimSpace(arch) + + m["arch"] = arch + + cr := regexp.MustCompile(`cr=[[:xdigit:]]+`).FindString(line) + cr = strings.TrimPrefix(cr, "cr=") + + m["cr"] = cr + } else if rLine2.MatchString(line) { + line = rLine2.FindString(line) + line = strings.TrimPrefix(line, `CPU: `) + + dataCache := regexp.MustCompile(`[[:print:]]+data cache`).FindString(line) + dataCache = strings.TrimSuffix(dataCache, "data cache") + dataCache = strings.TrimSpace(dataCache) + + m["data_cache"] = dataCache + + instructionCache := regexp.MustCompile(`,[[:print:]]+instruction cache`).FindString(line) + instructionCache = strings.TrimPrefix(instructionCache, ",") + instructionCache = strings.TrimSuffix(instructionCache, "instruction cache") + instructionCache = strings.TrimSpace(instructionCache) + + m["instruction_cache"] = instructionCache + } + } + + chanOutput <- m +} + +func parseModel(lines chan string, chanOutput chan jsonObject) { + m := make(jsonObject) + m["type"] = "model" + m["model"] = "" + + rLine := regexp.MustCompile(`(Machine model: [[:print:]]+)|(Machine: [[:print:]]+)`) + rLineEdison := regexp.MustCompile(`Linux version[[:print:]]+edison`) + rLineARTIK := regexp.MustCompile(`CPU EXYNOS3250`) + for line := range lines { + if rLine.MatchString(line) { + line = rLine.FindString(line) + line = strings.TrimPrefix(line, "Machine model: ") + line = strings.TrimPrefix(line, "Machine: ") + + m["model"] = strings.TrimSpace(line) + + break + } else if rLineEdison.MatchString(line) { + m["model"] = "Intel Edison" + + break + } else if rLineARTIK.MatchString(line) { + m["model"] = "SAMSUNG ARTIK5" + + break + } + } + + chanOutput <- m +} + +func parseDeviceFound(lines chan string, chanOutput chan jsonObject) { + list := make([]string, 0) + for line := range lines { + for _, e := range deviceTable { + if e.re.MatchString(line) { + list = append(list, e.name) + } + } + } + + m := make(jsonObject) + m["type"] = "device_found" + m["list"] = list + + chanOutput <- m +} + +func parseKernelCommandLine(lines chan string, chanOutput chan jsonObject) { + m := make(jsonObject) + m["type"] = "kernel_command_line" + m["kernel_command_line"] = "" + + rLine := regexp.MustCompile("Kernel command line: [[:print:]]+") + for line := range lines { + if rLine.MatchString(line) { + line = rLine.FindString(line) + + cmdline := strings.TrimPrefix(line, "Kernel command line: ") + cmdline = strings.TrimSpace(cmdline) + if strings.HasPrefix(cmdline, `"`) && strings.HasSuffix(cmdline, `"`) { + cmdline = strings.TrimPrefix(cmdline, `"`) + cmdline = strings.TrimSuffix(cmdline, `"`) + } + + m["kernel_command_line"] = cmdline + + break + } + } + + chanOutput <- m +} + +func parseCma(lines chan string, chanOutput chan jsonObject) { + m := make(jsonObject) + m["type"] = "cma" + m["size"] = "" + m["address"] = "" + + rLine := regexp.MustCompile("cma: Reserved [[:print:]]+ at [[:print:]]+") + for line := range lines { + if rLine.MatchString(line) { + line = rLine.FindString(line) + line = strings.TrimPrefix(line, "cma: Reserved ") + + size := regexp.MustCompile(`[[:print:]]+ at`).FindString(line) + size = strings.TrimSuffix(size, "at") + size = strings.TrimSpace(size) + + m["size"] = size + + address := regexp.MustCompile(`at [[:print:]]+`).FindString(line) + address = strings.TrimPrefix(address, "at") + address = strings.TrimSpace(address) + + m["address"] = address + + break + } + } + + chanOutput <- m +} + +func parseSlub(lines chan string, chanOutput chan jsonObject) { + m := make(jsonObject) + m["type"] = "slub" + m["hw_align"] = "" + m["order"] = "" + m["min_objects"] = "" + m["cpus"] = "" + m["nodes"] = "" + + rLine := regexp.MustCompile("SLUB: HWalign=[[:digit:]]+, Order=[[:digit:]]+-[[:digit:]]+, MinObjects=[[:digit:]]+, CPUs=[[:digit:]]+, Nodes=[[:digit:]]+") + for line := range lines { + if rLine.MatchString(line) { + line = rLine.FindString(line) + + hwAlign := regexp.MustCompile(`HWalign=[[:digit:]]+`).FindString(line) + hwAlign = strings.TrimPrefix(hwAlign, `HWalign=`) + + m["hw_align"] = hwAlign + + order := regexp.MustCompile(`Order=[[:digit:]]+-[[:digit:]]+`).FindString(line) + order = strings.TrimPrefix(order, `Order=`) + + m["order"] = order + + minObjects := regexp.MustCompile(`MinObjects=[[:digit:]]+`).FindString(line) + minObjects = strings.TrimPrefix(minObjects, `MinObjects=`) + + m["min_objects"] = minObjects + + cpus := regexp.MustCompile(`CPUs=[[:digit:]]+`).FindString(line) + cpus = strings.TrimPrefix(cpus, `CPUs=`) + + m["cpus"] = cpus + + nodes := regexp.MustCompile(`Nodes=[[:digit:]]+`).FindString(line) + nodes = strings.TrimPrefix(nodes, `Nodes=`) + + m["nodes"] = nodes + + break + } + } + + chanOutput <- m +} + +func parsePidMax(lines chan string, chanOutput chan jsonObject) { + m := make(jsonObject) + m["type"] = "pid_max" + m["default"] = "" + m["min"] = "" + + rLine := regexp.MustCompile("pid_max:[[:blank:]]+default:[[:blank:]]*[[:digit:]]+[[:blank:]]+minimum:[[:blank:]]*[[:digit:]]+") + for line := range lines { + if rLine.MatchString(line) { + line = rLine.FindString(line) + + m["default"] = extract(line, + `default:[[:blank:]]*[[:digit:]]+`, + `default:[[:blank:]]*`, + ``) + + m["min"] = extract(line, + `minimum:[[:blank:]]*[[:digit:]]+`, + `minimum:[[:blank:]]*`, + ``) + + break + } + } + + chanOutput <- m +} + +func parseWorkingset(lines chan string, chanOutput chan jsonObject) { + m := make(jsonObject) + m["type"] = "workingset" + m["timestamp bits"] = "" + m["max_order"] = "" + m["bucket_order"] = "" + + rLine := regexp.MustCompile("workingset: timestamp_bits=[[:digit:]]+ max_order=[[:digit:]]+ bucket_order=[[:digit:]]+") + for line := range lines { + if rLine.MatchString(line) { + line = rLine.FindString(line) + + m["timestamp_bits"] = extract(line, + `timestamp_bits=[[:digit:]]+`, + `timestamp_bits=`, + ``) + + m["max_order"] = extract(line, + `max_order=[[:digit:]]+`, + `max_order=`, + ``) + + m["bucket_order"] = extract(line, + `bucket_order=[[:digit:]]+`, + `bucket_order=`, + ``) + + break + } + } + + chanOutput <- m +} + +func removeBrackets(s string) string { + for strings.HasPrefix(s, "(") && strings.HasSuffix(s, ")") { + openCount := strings.Count(s, "(") + closeCount := strings.Count(s, ")") + + if openCount > closeCount { + s = strings.TrimPrefix(s, "(") + } else if openCount < closeCount { + s = strings.TrimSuffix(s, ")") + } else { + s = strings.TrimPrefix(s, "(") + s = strings.TrimSuffix(s, ")") + } + } + + return s +} + +func removeTimestamp(s string) string { + if reTimestamp.MatchString(s) { + t := reTimestamp.FindString(s) + s = strings.TrimPrefix(s, t) + } + return strings.TrimSpace(s) +} + +func extract(from string, chunk, prefix, suffix string) string { + reChunk, err := regexp.Compile(chunk) + if err != nil { + return "" + } + + rePrefix, err := regexp.Compile(prefix) + if err != nil { + return "" + } + + reSuffix, err := regexp.Compile(suffix) + if err != nil { + return "" + } + + b := reChunk.FindString(from) + + p := rePrefix.FindString(b) + b = strings.TrimPrefix(b, p) + + s := reSuffix.FindString(b) + b = strings.TrimSuffix(b, s) + + return b +} diff --git a/go/src/fullcycle/analog-kernel/parser/parser.go b/go/src/fullcycle/analog-kernel/parser/parser.go new file mode 100644 index 0000000..b148676 --- /dev/null +++ b/go/src/fullcycle/analog-kernel/parser/parser.go @@ -0,0 +1,250 @@ +package parser + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "strings" +) + +type jsonObject map[string]interface{} +type jsonArray []interface{} + +type Request struct { + Log []string `json:"log"` + Sheet Sheet `json:"sheet"` +} + +type Sheet struct { + LogID string `json:"log_id"` + Date string `json:"date"` + Target string `json:"target"` + Memory string `json:"memory"` + StartLine string `json:"start_line"` + + Hardware []SheetEntry `json:"hardware"` + OS []SheetEntry `json:"os"` + Device []SheetEntry `json:"device"` +} + +type SheetEntry struct { + Title string `json:"title"` + Check [][]string `json:"check"` + ErrorMessage []string `json:"error_message"` +} + +type Parser struct { + InChan chan string + OutChan chan jsonObject +} + +func New() *Parser { + parser := &Parser{} + return parser +} + +func (p *Parser) Parse(request *Request) string { + p.start() + for _, line := range request.Log { + p.InChan <- line + } + p.stop() + + return p.makeResult(request.Sheet) +} + +func (p *Parser) start() { + p.InChan = make(chan string, 100) + p.OutChan = make(chan jsonObject, 1) + + // Go parse functions + inputChanList := make([]chan string, len(parseFuncList)) + outputChanList := make([]chan jsonObject, len(parseFuncList)) + for i, parseFunc := range parseFuncList { + f := parseFunc + + inputChan := make(chan string, 10) + outputChan := make(chan jsonObject, 1) + + inputChanList[i] = inputChan + outputChanList[i] = outputChan + + go func() { + defer func() { + if r := recover(); r != nil { + //p.Fatal("Internal Error", r, string(debug.Stack())) + } + for range inputChan { + } + close(outputChan) + }() + f(inputChan, outputChan) + }() + } + + // Broadcast input + go func() { + for input := range p.InChan { + for _, inputChan := range inputChanList { + inputChan <- input + } + } + + for _, inputChan := range inputChanList { + close(inputChan) + } + }() + + // Merge output + go func() { + output := make(jsonObject) + + for _, outputChan := range outputChanList { + for parsed := range outputChan { + output[parsed["type"].(string)] = parsed + } + } + + p.OutChan <- output + close(p.OutChan) + }() +} + +func (p *Parser) stop() { + close(p.InChan) +} + +func (p *Parser) makeReport(result jsonObject, checklist []SheetEntry) ([]jsonObject, bool) { + var report []jsonObject + + totalPass := true + + for _, entry := range checklist { + reportEntry := make(jsonObject) + reportEntry["title"] = entry.Title + + pass := true + for _, c := range entry.Check { + o, ok := result[c[0]].(jsonObject) + if !ok { + reportEntry["result"] = "FAIL" + reportEntry["message"] = entry.ErrorMessage[0] + pass = false + break + } + switch o[c[1]].(type) { + case string: + if len(c[2]) > 0 { + v, ok := o[c[1]].(string) + if !ok { + reportEntry["result"] = "FAIL" + reportEntry["message"] = entry.ErrorMessage[0] + pass = false + break + } + if strings.Compare(v, c[2]) != 0 { + reportEntry["result"] = "FAIL" + reportEntry["message"] = entry.ErrorMessage[0] + pass = false + break + } + } + case []string: + if len(c[2]) > 0 { + l, ok := o[c[1]].([]string) + if !ok { + reportEntry["result"] = "FAIL" + reportEntry["message"] = entry.ErrorMessage[0] + pass = false + break + } + + found := false + for _, v := range l { + if strings.Compare(v, c[2]) == 0 { + found = true + } + } + if !found { + reportEntry["result"] = "FAIL" + reportEntry["message"] = entry.ErrorMessage[0] + pass = false + break + } + } + case []jsonObject: + if len(c[2]) > 0 { + list, ok := o[c[1]].([]jsonObject) + if !ok { + reportEntry["result"] = "FAIL" + reportEntry["message"] = entry.ErrorMessage[0] + pass = false + break + } + + found := false + for _, v := range list { + label := v["label"].(string) + if strings.Compare(label, c[2]) == 0 { + found = true + } + } + if !found { + reportEntry["result"] = "FAIL" + reportEntry["message"] = entry.ErrorMessage[0] + pass = false + break + } + } + default: + fmt.Printf("%v fail (type: %T)\n", c[1], o[c[1]]) + reportEntry["result"] = "FAIL" + pass = false + } + } + if pass { + reportEntry["result"] = "PASS" + } else { + totalPass = false + } + report = append(report, reportEntry) + } + + return report, totalPass +} + +func (p *Parser) makeResult(sheet Sheet) string { + output := make(jsonObject) + + result := <-p.OutChan + report := make(jsonObject) + + pass := true + totalPass := true + + result["memory_size"] = sheet.Memory + + report["log_id"] = sheet.LogID + report["date"] = sheet.Date + report["target"] = sheet.Target + + report["hardware"], pass = p.makeReport(result, sheet.Hardware) + totalPass = totalPass && pass + report["os"], pass = p.makeReport(result, sheet.OS) + totalPass = totalPass && pass + report["device"], pass = p.makeReport(result, sheet.Device) + totalPass = totalPass && pass + + if totalPass { + report["pass"] = "PASS" + } + + output["result"] = result + output["report"] = report + + b, err := json.MarshalIndent(output, "", " ") + if err == nil { + ioutil.WriteFile("anal-kernel-response.json", b, 0644) + } + return string(b) +} diff --git a/go/src/fullcycle/analog-kernel/sheet-sample.json b/go/src/fullcycle/analog-kernel/sheet-sample.json new file mode 100644 index 0000000..ff39aed --- /dev/null +++ b/go/src/fullcycle/analog-kernel/sheet-sample.json @@ -0,0 +1,203 @@ +{ + "log_id": "012-3233-4423", + "date": "2018/04/18", + + "target": "raspberry pi3", + "hardware": [ + { + "title": "Check the CPU type", + "check": [ + ["cpu", "name", "ARMv7 Processor"] + ], + "error_message": [ + "Not found in booting log messages" + ] + }, + { + "title": "Check memory size", + "check": [ + ["memory", "total", "970752K"] + ], + "error_message": [ + "Not found in booting log messages", + "Wrong size" + ] + }, + { + "title": "Check board model type", + "check": [ + ["model", "model", "Raspberry Pi 3 Model B Rev 1.2"] + ], + "error_message": [ + "Not found in booting log messages", + "Wrong model" + ] + }, + { + "title": "Check CMA", + "check": [ + ["cma", "size", ""] + ], + "error_message": [ + "Not found in booting log messages" + ] + } + ], + "os": [ + { + "title": "Check OS type (Linux)", + "check": [ + ["linux", "type", "linux"] + ], + "error_message": [ + "Not found in booting log messages" + ] + }, + { + "title": "Check kernel memory layout", + "check": [ + ["memory_layout", "layout", "vector"], + ["memory_layout", "layout", "fixmap"], + ["memory_layout", "layout", "vmalloc"], + ["memory_layout", "layout", "lowmem"], + ["memory_layout", "layout", "modules"], + ["memory_layout", "layout", ".text"], + ["memory_layout", "layout", ".init"], + ["memory_layout", "layout", ".data"], + ["memory_layout", "layout", ".bss"] + ], + "error_message": [ + "Not found in booting log messages" + ] + }, + { + "title": "Check kernel hash tables", + "check": [ + ["hash_tables", "list", "PID"], + ["hash_tables", "list", "Dentry cache"], + ["hash_tables", "list", "Inode-cache"], + ["hash_tables", "list", "Mount-cache"], + ["hash_tables", "list", "Mountpoint-cache"], + ["hash_tables", "list", "futex"], + ["hash_tables", "list", "VFS: Dquot-cache"], + ["hash_tables", "list", "TCP established"], + ["hash_tables", "list", "TCP bind"], + ["hash_tables", "list", "UDP"], + ["hash_tables", "list", "UDP-Lite"] + ], + "error_message": [ + "Not found in booting log messages" + ] + } + ], + "device": [ + { + "title": "Check driver existance (UART)", + "check": [ + ["device_found", "list", "AMBA PL011 UART Device"] + ], + "error_message": [ + "Not found in booting log messages" + ] + }, + { + "title": "Check driver existance (Mailbox)", + "check": [ + ["device_found", "list", "BCM2835 Mailbox"] + ], + "error_message": [ + "Not found in booting log messages" + ] + }, + { + "title": "Check driver existance (DMA)", + "check": [ + ["device_found", "list", "BCM2835 DMA"] + ], + "error_message": [ + "Not found in booting log messages" + ] + }, + { + "title": "Check driver existance (SCSI)", + "check": [ + ["device_found", "list", "SCSI subsystem"] + ], + "error_message": [ + "Not found in booting log messages" + ] + }, + { + "title": "Check driver existance (Ethernet)", + "check": [ + ["device_found", "list", "SMSC LAN95XX Based USB 2.0 10/100 Ethernet Device"] + ], + "error_message": [ + "Not found in booting log messages" + ] + }, + { + "title": "Check driver existance (Watchdog Timer)", + "check": [ + ["device_found", "list", "BCM2835 Watchdog Timer"] + ], + "error_message": [ + "Not found in booting log messages" + ] + }, + { + "title": "Check driver existance (USB Mass Storage)", + "check": [ + ["device_found", "list", "USB Mass Storage"] + ], + "error_message": [ + "Not found in booting log messages" + ] + }, + { + "title": "Check driver existance (BCM FrameBuffer)", + "check": [ + ["device_found", "list", "BCM2708FB"] + ], + "error_message": [ + "Not found in booting log messages" + ] + }, + { + "title": "Check driver existance (Random Generator)", + "check": [ + ["device_found", "list", "BCM2835 RNG"] + ], + "error_message": [ + "Not found in booting log messages" + ] + }, + { + "title": "Check driver existance (SDHCI)", + "check": [ + ["device_found", "list", "Secure Digital Host Controller Interface"] + ], + "error_message": [ + "Not found in booting log messages" + ] + }, + { + "title": "Check driver existance (MMC:SDHC)", + "check": [ + ["device_found", "list", "SDHC Card"] + ], + "error_message": [ + "Not found in booting log messages" + ] + }, + { + "title": "Check driver existance (MMC:SDIO)", + "check": [ + ["device_found", "list", "SDIO Card"] + ], + "error_message": [ + "Not found in booting log messages" + ] + } + ] +} diff --git a/go/src/fullcycle/analog-kernel/test.sh b/go/src/fullcycle/analog-kernel/test.sh new file mode 100755 index 0000000..cf75404 --- /dev/null +++ b/go/src/fullcycle/analog-kernel/test.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +cat input-sample | ./analog-kernel sample diff --git a/go/src/fullcycle/do-iperf/main.go b/go/src/fullcycle/do-iperf/main.go new file mode 100644 index 0000000..9f693a8 --- /dev/null +++ b/go/src/fullcycle/do-iperf/main.go @@ -0,0 +1,56 @@ +package main + +import ( + "bufio" + "fmt" + "io" + "log" + "os" + "os/exec" +) + +func main() { + var host string + var out io.Writer + + if l := len(os.Args); l == 1 { + host = "172.30.0.1" + out = os.Stdout + } else if l == 2 { + host = os.Args[1] + out = os.Stdout + } else { + f, err := os.OpenFile(os.Args[2], os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) + if err != nil { + log.Fatal(err) + } + defer f.Close() + + host = os.Args[1] + out = f + } + + test("hw-wifi", host, out) +} + +func test(code, host string, out io.Writer) { + c := exec.Command("iperf", "-c", host, "-i", "1", "-t", "10") + stdout, err := c.StdoutPipe() + + err = c.Start() + if err != nil { + log.Fatal(err) + } + + state := 0 + + s := bufio.NewScanner(stdout) + for s.Scan() { + fmt.Fprintf(out, "{\"code\": \"%v\", \"state\": %v, \"data\": \"%v\", \"timeout\": 10}\n", code, state, s.Text()) + if state < 90 { + state += 10 + } + } + + fmt.Fprintf(out, "{\"code\": \"%v\", \"state\": 100, \"data\": \"\", \"timeout\": 10}\n", code) +} -- 2.1.4